Index: test/CodeGen/AArch64/demorgan-extra.ll
===================================================================
--- /dev/null
+++ test/CodeGen/AArch64/demorgan-extra.ll
@@ -0,0 +1,494 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -o - %s | FileCheck %s
+
+; There is a identical twin test in test/Transforms/InstCombine/demorgan-extra.ll
+; Please keep them in sync! :)
+
+declare void @use32(i32)
+declare i32 @gen32()
+
+; ============================================================================ ;
+
+; ~(~A & B) --> (A | ~B)
+
+define i32 @demorgan_nand(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and w8, w0, w1
+; CHECK-NEXT:    orn w0, w8, w1
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_const(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_const:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov w8, #-43
+; CHECK-NEXT:    orr w0, w0, w8
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, 42
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define <2 x i32> @demorgan_nand_vec(<2 x i32> %A, <2 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    bic v0.8b, v1.8b, v0.8b
+; CHECK-NEXT:    mvn v0.8b, v0.8b
+; CHECK-NEXT:    ret
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, %B
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nand_vec_undef(<3 x i32> %A, <3 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_undef:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    bic v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = and <3 x i32> %notx, %B
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nand_vec_splatconst(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_splatconst:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    movi v1.2s, #42
+; CHECK-NEXT:    bic v0.8b, v1.8b, v0.8b
+; CHECK-NEXT:    mvn v0.8b, v0.8b
+; CHECK-NEXT:    ret
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, <i32 42, i32 42>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nand_vec_const_undef(<3 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_const_undef:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    movi v1.4s, #42
+; CHECK-NEXT:    bic v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = and <3 x i32> %notx, <i32 42, i32 undef, i32 42>
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nand_vec_const(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_const:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    adrp x8, .LCPI6_0
+; CHECK-NEXT:    ldr d1, [x8, :lo12:.LCPI6_0]
+; CHECK-NEXT:    bic v0.8b, v1.8b, v0.8b
+; CHECK-NEXT:    mvn v0.8b, v0.8b
+; CHECK-NEXT:    ret
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, <i32 42, i32 31>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nand_vec_128bit(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_128bit:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    bic v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
+  %c = and <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 -1, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nand_vec_128bit_undef(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_128bit_undef:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    bic v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 undef, i32 -1>
+  %c = and <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 undef, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define i32 @demorgan_nand_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_commutative:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    stp x19, x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    mov w19, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    and w8, w19, w0
+; CHECK-NEXT:    orn w0, w8, w0
+; CHECK-NEXT:    ldp x19, x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %B = call i32 @gen32()
+  %notx = xor i32 %A, -1
+  %c = and i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_extraxor(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_extraxor:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    str x20, [sp, #-32]! // 8-byte Folded Spill
+; CHECK-NEXT:    stp x19, x30, [sp, #16] // 8-byte Folded Spill
+; CHECK-NEXT:    mov w19, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    mov w20, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    eor w8, w20, w0
+; CHECK-NEXT:    and w9, w19, w8
+; CHECK-NEXT:    ldp x19, x30, [sp, #16] // 8-byte Folded Reload
+; CHECK-NEXT:    orn w0, w9, w8
+; CHECK-NEXT:    ldr x20, [sp], #32 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_extraxor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_extraxor_commutative:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    str x20, [sp, #-32]! // 8-byte Folded Spill
+; CHECK-NEXT:    stp x19, x30, [sp, #16] // 8-byte Folded Spill
+; CHECK-NEXT:    mov w19, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    mov w20, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    eor w8, w20, w0
+; CHECK-NEXT:    and w9, w19, w8
+; CHECK-NEXT:    ldp x19, x30, [sp, #16] // 8-byte Folded Reload
+; CHECK-NEXT:    orn w0, w9, w8
+; CHECK-NEXT:    ldr x20, [sp], #32 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = and i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_badxor0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_badxor0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    eor w8, w0, #0x1
+; CHECK-NEXT:    and w8, w8, w1
+; CHECK-NEXT:    mvn w0, w8
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, 1 ; not -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_badxor1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_badxor1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    bic w8, w1, w0
+; CHECK-NEXT:    eor w0, w8, #0x1
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, 1 ; not -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_oneuse0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_oneuse0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    stp x19, x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    mvn w8, w0
+; CHECK-NEXT:    bic w9, w1, w0
+; CHECK-NEXT:    mov w0, w8
+; CHECK-NEXT:    mvn w19, w9
+; CHECK-NEXT:    bl use32
+; CHECK-NEXT:    mov w0, w19
+; CHECK-NEXT:    ldp x19, x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %notx)
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_oneuse1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_oneuse1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    stp x19, x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    bic w0, w1, w0
+; CHECK-NEXT:    mvn w19, w0
+; CHECK-NEXT:    bl use32
+; CHECK-NEXT:    mov w0, w19
+; CHECK-NEXT:    ldp x19, x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %c)
+  ret i32 %notc
+}
+
+; ============================================================================ ;
+
+; ~(~A | B) --> (A & ~B)
+
+define i32 @demorgan_nor(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    orn w8, w1, w0
+; CHECK-NEXT:    mvn w0, w8
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_const(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_const:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov w8, #-43
+; CHECK-NEXT:    and w0, w0, w8
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, 42
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define <2 x i32> @demorgan_nor_vec(<2 x i32> %A, <2 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    orn v0.8b, v1.8b, v0.8b
+; CHECK-NEXT:    mvn v0.8b, v0.8b
+; CHECK-NEXT:    ret
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, %B
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nor_vec_undef(<3 x i32> %A, <3 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_undef:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    orn v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = or <3 x i32> %notx, %B
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nor_vec_splatconst(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_splatconst:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mvn v0.8b, v0.8b
+; CHECK-NEXT:    orr v0.2s, #42
+; CHECK-NEXT:    mvn v0.8b, v0.8b
+; CHECK-NEXT:    ret
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, <i32 42, i32 42>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nor_vec_const_undef(<3 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_const_undef:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    orr v0.4s, #42
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = or <3 x i32> %notx, <i32 42, i32 undef, i32 42>
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nor_vec_const(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_const:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    adrp x8, .LCPI22_0
+; CHECK-NEXT:    ldr d1, [x8, :lo12:.LCPI22_0]
+; CHECK-NEXT:    orn v0.8b, v1.8b, v0.8b
+; CHECK-NEXT:    mvn v0.8b, v0.8b
+; CHECK-NEXT:    ret
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, <i32 42, i32 31>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nor_vec_128bit(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_128bit:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    orn v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
+  %c = or <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 -1, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nor_vec_128bit_undef(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_128bit_undef:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    orn v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    mvn v0.16b, v0.16b
+; CHECK-NEXT:    ret
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 undef, i32 -1>
+  %c = or <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 undef, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define i32 @demorgan_nor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_commutative:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    stp x19, x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    mov w19, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    orn w8, w0, w19
+; CHECK-NEXT:    mvn w0, w8
+; CHECK-NEXT:    ldp x19, x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %B = call i32 @gen32()
+  %notx = xor i32 %A, -1
+  %c = or i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_extraxor(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_extraxor:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    str x20, [sp, #-32]! // 8-byte Folded Spill
+; CHECK-NEXT:    stp x19, x30, [sp, #16] // 8-byte Folded Spill
+; CHECK-NEXT:    mov w19, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    mov w20, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    eor w8, w20, w0
+; CHECK-NEXT:    orn w8, w8, w19
+; CHECK-NEXT:    ldp x19, x30, [sp, #16] // 8-byte Folded Reload
+; CHECK-NEXT:    mvn w0, w8
+; CHECK-NEXT:    ldr x20, [sp], #32 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_extraxor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_extraxor_commutative:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    str x20, [sp, #-32]! // 8-byte Folded Spill
+; CHECK-NEXT:    stp x19, x30, [sp, #16] // 8-byte Folded Spill
+; CHECK-NEXT:    mov w19, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    mov w20, w0
+; CHECK-NEXT:    bl gen32
+; CHECK-NEXT:    eor w8, w20, w0
+; CHECK-NEXT:    orn w8, w8, w19
+; CHECK-NEXT:    ldp x19, x30, [sp, #16] // 8-byte Folded Reload
+; CHECK-NEXT:    mvn w0, w8
+; CHECK-NEXT:    ldr x20, [sp], #32 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = or i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_badxor0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_badxor0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    eor w8, w0, #0x1
+; CHECK-NEXT:    orr w8, w8, w1
+; CHECK-NEXT:    mvn w0, w8
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, 1 ; not -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_badxor1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_badxor1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    orn w8, w1, w0
+; CHECK-NEXT:    eor w0, w8, #0x1
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, 1 ; not -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_oneuse0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_oneuse0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    stp x19, x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    mvn w8, w0
+; CHECK-NEXT:    orn w9, w1, w0
+; CHECK-NEXT:    mov w0, w8
+; CHECK-NEXT:    mvn w19, w9
+; CHECK-NEXT:    bl use32
+; CHECK-NEXT:    mov w0, w19
+; CHECK-NEXT:    ldp x19, x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %notx)
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_oneuse1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_oneuse1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    stp x19, x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    orn w0, w1, w0
+; CHECK-NEXT:    mvn w19, w0
+; CHECK-NEXT:    bl use32
+; CHECK-NEXT:    mov w0, w19
+; CHECK-NEXT:    ldp x19, x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %c)
+  ret i32 %notc
+}
+
+; ============================================================================ ;
Index: test/CodeGen/X86/demorgan-extra.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/demorgan-extra.ll
@@ -0,0 +1,534 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -o - %s | FileCheck %s
+
+; There is a identical twin test in test/Transforms/InstCombine/demorgan-extra.ll
+; Please keep them in sync! :)
+
+declare void @use32(i32)
+declare i32 @gen32()
+
+; ============================================================================ ;
+
+; ~(~A & B) --> (A | ~B)
+
+define i32 @demorgan_nand(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    andl %esi, %edi
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_const(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_const:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    orl $-43, %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, 42
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define <2 x i32> @demorgan_nand_vec(<2 x i32> %A, <2 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movaps {{.*#+}} xmm2 = [4294967295,4294967295]
+; CHECK-NEXT:    xorps %xmm2, %xmm0
+; CHECK-NEXT:    andps %xmm1, %xmm0
+; CHECK-NEXT:    xorps %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, %B
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nand_vec_undef(<3 x i32> %A, <3 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_undef:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm2, %xmm2
+; CHECK-NEXT:    pandn %xmm1, %xmm0
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = and <3 x i32> %notx, %B
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nand_vec_splatconst(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_splatconst:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    andnps {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, <i32 42, i32 42>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nand_vec_const_undef(<3 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_const_undef:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm1, %xmm1
+; CHECK-NEXT:    pandn {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    pxor %xmm1, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = and <3 x i32> %notx, <i32 42, i32 undef, i32 42>
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nand_vec_const(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_const:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    andnps {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, <i32 42, i32 31>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nand_vec_128bit(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_128bit:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm2, %xmm2
+; CHECK-NEXT:    pandn %xmm1, %xmm0
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
+  %c = and <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 -1, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nand_vec_128bit_undef(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nand_vec_128bit_undef:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm2, %xmm2
+; CHECK-NEXT:    pandn %xmm1, %xmm0
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 undef, i32 -1>
+  %c = and <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 undef, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define i32 @demorgan_nand_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_commutative:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    andl %ebx, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    retq
+  %B = call i32 @gen32()
+  %notx = xor i32 %A, -1
+  %c = and i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_extraxor(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_extraxor:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    movl %eax, %ebp
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    xorl %ebp, %eax
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    andl %ebx, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    addq $8, %rsp
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    retq
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_extraxor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nand_extraxor_commutative:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    movl %eax, %ebp
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    xorl %ebp, %eax
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    andl %ebx, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    addq $8, %rsp
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    retq
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = and i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_badxor0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_badxor0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl $1, %edi
+; CHECK-NEXT:    andl %esi, %edi
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, 1 ; not -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_badxor1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_badxor1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    andl %esi, %edi
+; CHECK-NEXT:    xorl $1, %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, 1 ; not -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_oneuse0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_oneuse0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    movl %esi, %ebx
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    andl %edi, %ebx
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    callq use32
+; CHECK-NEXT:    movl %ebx, %eax
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %notx)
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_oneuse1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nand_oneuse1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    andl %esi, %edi
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    callq use32
+; CHECK-NEXT:    movl %ebx, %eax
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %c)
+  ret i32 %notc
+}
+
+; ============================================================================ ;
+
+; ~(~A | B) --> (A & ~B)
+
+define i32 @demorgan_nor(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    orl %esi, %edi
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_const(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_const:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    andl $-43, %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, 42
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define <2 x i32> @demorgan_nor_vec(<2 x i32> %A, <2 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movaps {{.*#+}} xmm2 = [4294967295,4294967295]
+; CHECK-NEXT:    xorps %xmm2, %xmm0
+; CHECK-NEXT:    orps %xmm1, %xmm0
+; CHECK-NEXT:    xorps %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, %B
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nor_vec_undef(<3 x i32> %A, <3 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_undef:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm2, %xmm2
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    por %xmm1, %xmm0
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = or <3 x i32> %notx, %B
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nor_vec_splatconst(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_splatconst:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movaps {{.*#+}} xmm1 = [4294967295,4294967295]
+; CHECK-NEXT:    xorps %xmm1, %xmm0
+; CHECK-NEXT:    orps {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    xorps %xmm1, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, <i32 42, i32 42>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nor_vec_const_undef(<3 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_const_undef:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm1, %xmm1
+; CHECK-NEXT:    pxor %xmm1, %xmm0
+; CHECK-NEXT:    por {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    pxor %xmm1, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = or <3 x i32> %notx, <i32 42, i32 undef, i32 42>
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nor_vec_const(<2 x i32> %A) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_const:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movaps {{.*#+}} xmm1 = [4294967295,4294967295]
+; CHECK-NEXT:    xorps %xmm1, %xmm0
+; CHECK-NEXT:    orps {{.*}}(%rip), %xmm0
+; CHECK-NEXT:    xorps %xmm1, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, <i32 42, i32 31>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nor_vec_128bit(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_128bit:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm2, %xmm2
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    por %xmm1, %xmm0
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
+  %c = or <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 -1, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nor_vec_128bit_undef(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: demorgan_nor_vec_128bit_undef:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pcmpeqd %xmm2, %xmm2
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    por %xmm1, %xmm0
+; CHECK-NEXT:    pxor %xmm2, %xmm0
+; CHECK-NEXT:    retq
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 undef, i32 -1>
+  %c = or <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 undef, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define i32 @demorgan_nor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_commutative:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    orl %ebx, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    retq
+  %B = call i32 @gen32()
+  %notx = xor i32 %A, -1
+  %c = or i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_extraxor(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_extraxor:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    movl %eax, %ebp
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    xorl %ebp, %eax
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    orl %ebx, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    addq $8, %rsp
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    retq
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_extraxor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: demorgan_nor_extraxor_commutative:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    movl %eax, %ebp
+; CHECK-NEXT:    callq gen32
+; CHECK-NEXT:    xorl %ebp, %eax
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    orl %ebx, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    addq $8, %rsp
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    retq
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = or i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_badxor0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_badxor0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl $1, %edi
+; CHECK-NEXT:    orl %esi, %edi
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, 1 ; not -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_badxor1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_badxor1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    orl %esi, %edi
+; CHECK-NEXT:    xorl $1, %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, 1 ; not -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_oneuse0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_oneuse0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    movl %esi, %ebx
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    orl %edi, %ebx
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    callq use32
+; CHECK-NEXT:    movl %ebx, %eax
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %notx)
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_oneuse1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: demorgan_nor_oneuse1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    orl %esi, %edi
+; CHECK-NEXT:    movl %edi, %ebx
+; CHECK-NEXT:    notl %ebx
+; CHECK-NEXT:    callq use32
+; CHECK-NEXT:    movl %ebx, %eax
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    retq
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %c)
+  ret i32 %notc
+}
+
+; ============================================================================ ;
Index: test/Transforms/InstCombine/demorgan-extra.ll
===================================================================
--- /dev/null
+++ test/Transforms/InstCombine/demorgan-extra.ll
@@ -0,0 +1,442 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; There is a identical twin test in test/CodeGen/{X86,AArch64}/demorgan-extra.ll
+; Please keep them in sync! :)
+
+declare void @use32(i32)
+declare i32 @gen32()
+
+; ============================================================================ ;
+
+; ~(~A & B) --> (A | ~B)
+
+define i32 @demorgan_nand(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nand(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = or i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_const(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nand_const(
+; CHECK-NEXT:    [[NOTC1:%.*]] = or i32 [[A:%.*]], -43
+; CHECK-NEXT:    ret i32 [[NOTC1]]
+;
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, 42
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define <2 x i32> @demorgan_nand_vec(<2 x i32> %A, <2 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_vec(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <2 x i32> [[B:%.*]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = or <2 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <2 x i32> [[NOTC]]
+;
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, %B
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nand_vec_undef(<3 x i32> %A, <3 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_vec_undef(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <3 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = or <3 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <3 x i32> [[NOTC]]
+;
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = and <3 x i32> %notx, %B
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nand_vec_splatconst(<2 x i32> %A) nounwind {
+; CHECK-LABEL: @demorgan_nand_vec_splatconst(
+; CHECK-NEXT:    [[NOTC1:%.*]] = or <2 x i32> [[A:%.*]], <i32 -43, i32 -43>
+; CHECK-NEXT:    ret <2 x i32> [[NOTC1]]
+;
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, <i32 42, i32 42>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nand_vec_const_undef(<3 x i32> %A) nounwind {
+; CHECK-LABEL: @demorgan_nand_vec_const_undef(
+; CHECK-NEXT:    [[NOTC:%.*]] = or <3 x i32> [[A:%.*]], <i32 -43, i32 undef, i32 -43>
+; CHECK-NEXT:    ret <3 x i32> [[NOTC]]
+;
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = and <3 x i32> %notx, <i32 42, i32 undef, i32 42>
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nand_vec_const(<2 x i32> %A) nounwind {
+; CHECK-LABEL: @demorgan_nand_vec_const(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor <2 x i32> [[A:%.*]], <i32 63, i32 63>
+; CHECK-NEXT:    [[C:%.*]] = and <2 x i32> [[NOTX]], <i32 42, i32 31>
+; CHECK-NEXT:    [[NOTC:%.*]] = xor <2 x i32> [[C]], <i32 -1, i32 -1>
+; CHECK-NEXT:    ret <2 x i32> [[NOTC]]
+;
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = and <2 x i32> %notx, <i32 42, i32 31>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nand_vec_128bit(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_vec_128bit(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <4 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = or <4 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <4 x i32> [[NOTC]]
+;
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
+  %c = and <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 -1, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nand_vec_128bit_undef(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_vec_128bit_undef(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <4 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = or <4 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <4 x i32> [[NOTC]]
+;
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 undef, i32 -1>
+  %c = and <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 undef, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define i32 @demorgan_nand_commutative(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nand_commutative(
+; CHECK-NEXT:    [[B:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = or i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %B = call i32 @gen32()
+  %notx = xor i32 %A, -1
+  %c = and i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_extraxor(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nand_extraxor(
+; CHECK-NEXT:    [[V:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[Z:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[B:%.*]] = xor i32 [[V]], [[Z]]
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = or i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_extraxor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nand_extraxor_commutative(
+; CHECK-NEXT:    [[V:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[Z:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[B:%.*]] = xor i32 [[V]], [[Z]]
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = or i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = and i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_badxor0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_badxor0(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], 1
+; CHECK-NEXT:    [[C:%.*]] = and i32 [[NOTX]], [[B:%.*]]
+; CHECK-NEXT:    [[NOTC:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, 1 ; not -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_badxor1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_badxor1(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], -1
+; CHECK-NEXT:    [[C:%.*]] = and i32 [[NOTX]], [[B:%.*]]
+; CHECK-NEXT:    [[NOTC:%.*]] = xor i32 [[C]], 1
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, 1 ; not -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_oneuse0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_oneuse0(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], -1
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = or i32 [[B_NOT]], [[A]]
+; CHECK-NEXT:    call void @use32(i32 [[NOTX]]) #0
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %notx)
+  ret i32 %notc
+}
+
+define i32 @demorgan_nand_oneuse1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nand_oneuse1(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], -1
+; CHECK-NEXT:    [[C:%.*]] = and i32 [[NOTX]], [[B:%.*]]
+; CHECK-NEXT:    [[NOTC:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT:    call void @use32(i32 [[C]]) #0
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = and i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %c)
+  ret i32 %notc
+}
+
+; ============================================================================ ;
+
+; ~(~A | B) --> (A & ~B)
+
+define i32 @demorgan_nor(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nor(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = and i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_const(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nor_const(
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], -43
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, 42
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define <2 x i32> @demorgan_nor_vec(<2 x i32> %A, <2 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_vec(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <2 x i32> [[B:%.*]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = and <2 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <2 x i32> [[NOTC]]
+;
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, %B
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nor_vec_undef(<3 x i32> %A, <3 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_vec_undef(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <3 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = and <3 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <3 x i32> [[NOTC]]
+;
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = or <3 x i32> %notx, %B
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nor_vec_splatconst(<2 x i32> %A) nounwind {
+; CHECK-LABEL: @demorgan_nor_vec_splatconst(
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], <i32 -43, i32 -43>
+; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
+;
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, <i32 42, i32 42>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <3 x i32> @demorgan_nor_vec_const_undef(<3 x i32> %A) nounwind {
+; CHECK-LABEL: @demorgan_nor_vec_const_undef(
+; CHECK-NEXT:    [[NOTC:%.*]] = and <3 x i32> [[A:%.*]], <i32 -43, i32 undef, i32 -43>
+; CHECK-NEXT:    ret <3 x i32> [[NOTC]]
+;
+  %notx = xor <3 x i32> %A, <i32 -1, i32 undef, i32 -1>
+  %c = or <3 x i32> %notx, <i32 42, i32 undef, i32 42>
+  %notc = xor <3 x i32> %c, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %notc
+}
+
+define <2 x i32> @demorgan_nor_vec_const(<2 x i32> %A) nounwind {
+; CHECK-LABEL: @demorgan_nor_vec_const(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor <2 x i32> [[A:%.*]], <i32 -11, i32 -11>
+; CHECK-NEXT:    [[C:%.*]] = or <2 x i32> [[NOTX]], <i32 42, i32 31>
+; CHECK-NEXT:    [[NOTC:%.*]] = xor <2 x i32> [[C]], <i32 -1, i32 -1>
+; CHECK-NEXT:    ret <2 x i32> [[NOTC]]
+;
+  %notx = xor <2 x i32> %A, <i32 -1, i32 -1>
+  %c = or <2 x i32> %notx, <i32 42, i32 31>
+  %notc = xor <2 x i32> %c, <i32 -1, i32 -1>
+  ret <2 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nor_vec_128bit(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_vec_128bit(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <4 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = and <4 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <4 x i32> [[NOTC]]
+;
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
+  %c = or <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 -1, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define <4 x i32> @demorgan_nor_vec_128bit_undef(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_vec_128bit_undef(
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor <4 x i32> [[B:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
+; CHECK-NEXT:    [[NOTC:%.*]] = and <4 x i32> [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret <4 x i32> [[NOTC]]
+;
+  %notx = xor <4 x i32> %A, <i32 -1, i32 -1, i32 undef, i32 -1>
+  %c = or <4 x i32> %notx, %B
+  %notc = xor <4 x i32> %c, <i32 -1, i32 -1, i32 undef, i32 -1>
+  ret <4 x i32> %notc
+}
+
+define i32 @demorgan_nor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nor_commutative(
+; CHECK-NEXT:    [[B:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = and i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %B = call i32 @gen32()
+  %notx = xor i32 %A, -1
+  %c = or i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_extraxor(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nor_extraxor(
+; CHECK-NEXT:    [[V:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[Z:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[B:%.*]] = xor i32 [[V]], [[Z]]
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = and i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_extraxor_commutative(i32 %A) nounwind {
+; CHECK-LABEL: @demorgan_nor_extraxor_commutative(
+; CHECK-NEXT:    [[V:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[Z:%.*]] = call i32 @gen32() #0
+; CHECK-NEXT:    [[B:%.*]] = xor i32 [[V]], [[Z]]
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = and i32 [[B_NOT]], [[A:%.*]]
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %V = call i32 @gen32()
+  %Z = call i32 @gen32()
+  %B = xor i32 %V, %Z ; not with -1
+  %notx = xor i32 %A, -1
+  %c = or i32 %B, %notx ; swapped
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_badxor0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_badxor0(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], 1
+; CHECK-NEXT:    [[C:%.*]] = or i32 [[NOTX]], [[B:%.*]]
+; CHECK-NEXT:    [[NOTC:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, 1 ; not -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_badxor1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_badxor1(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], -1
+; CHECK-NEXT:    [[C:%.*]] = or i32 [[NOTX]], [[B:%.*]]
+; CHECK-NEXT:    [[NOTC:%.*]] = xor i32 [[C]], 1
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, 1 ; not -1
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_oneuse0(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_oneuse0(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], -1
+; CHECK-NEXT:    [[B_NOT:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[NOTC:%.*]] = and i32 [[B_NOT]], [[A]]
+; CHECK-NEXT:    call void @use32(i32 [[NOTX]]) #0
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %notx)
+  ret i32 %notc
+}
+
+define i32 @demorgan_nor_oneuse1(i32 %A, i32 %B) nounwind {
+; CHECK-LABEL: @demorgan_nor_oneuse1(
+; CHECK-NEXT:    [[NOTX:%.*]] = xor i32 [[A:%.*]], -1
+; CHECK-NEXT:    [[C:%.*]] = or i32 [[NOTX]], [[B:%.*]]
+; CHECK-NEXT:    [[NOTC:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT:    call void @use32(i32 [[C]]) #0
+; CHECK-NEXT:    ret i32 [[NOTC]]
+;
+  %notx = xor i32 %A, -1
+  %c = or i32 %notx, %B
+  %notc = xor i32 %c, -1
+  call void @use32(i32 %c)
+  ret i32 %notc
+}
+
+; ============================================================================ ;