diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -14099,8 +14099,8 @@ } } - // Transform br(xor(x, y)) -> br(x != y) - // Transform br(xor(xor(x,y), 1)) -> br (x == y) + // Transform (brcond (xor x, y)) -> (brcond (setcc, x, y, ne)) + // Transform (brcond (xor (xor x, y), -1)) -> (brcond (setcc, x, y, eq)) if (N.getOpcode() == ISD::XOR) { // Because we may call this on a speculatively constructed // SimplifiedSetCC Node, we need to simplify this node first. @@ -14124,16 +14124,17 @@ if (N.getOpcode() != ISD::XOR) return N; - SDNode *TheXor = N.getNode(); - - SDValue Op0 = TheXor->getOperand(0); - SDValue Op1 = TheXor->getOperand(1); + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); if (Op0.getOpcode() != ISD::SETCC && Op1.getOpcode() != ISD::SETCC) { bool Equal = false; - if (isOneConstant(Op0) && Op0.hasOneUse() && - Op0.getOpcode() == ISD::XOR) { - TheXor = Op0.getNode(); + // (brcond (xor (xor x, y), -1)) -> (brcond (setcc x, y, eq)) + if (isBitwiseNot(N) && Op0.hasOneUse() && Op0.getOpcode() == ISD::XOR && + Op0.getValueType() == MVT::i1) { + N = Op0; + Op0 = N->getOperand(0); + Op1 = N->getOperand(1); Equal = true; } @@ -14141,7 +14142,7 @@ if (LegalTypes) SetCCVT = getSetCCResultType(SetCCVT); // Replace the uses of XOR with SETCC - return DAG.getSetCC(SDLoc(TheXor), SetCCVT, Op0, Op1, + return DAG.getSetCC(SDLoc(N), SetCCVT, Op0, Op1, Equal ? ISD::SETEQ : ISD::SETNE); } } diff --git a/llvm/test/CodeGen/AArch64/cmp-bool.ll b/llvm/test/CodeGen/AArch64/cmp-bool.ll --- a/llvm/test/CodeGen/AArch64/cmp-bool.ll +++ b/llvm/test/CodeGen/AArch64/cmp-bool.ll @@ -25,9 +25,8 @@ define void @bool_ne(i1 zeroext %a, i1 zeroext %b, void ()* nocapture %c) nounwind { ; CHECK-LABEL: bool_ne: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: eor w8, w0, w1 -; CHECK-NEXT: cmp w8, #1 // =1 -; CHECK-NEXT: b.ne .LBB1_2 +; CHECK-NEXT: cmp w0, w1 +; CHECK-NEXT: b.eq .LBB1_2 ; CHECK-NEXT: // %bb.1: // %if.then ; CHECK-NEXT: br x2 ; CHECK-NEXT: .LBB1_2: // %if.end diff --git a/llvm/test/CodeGen/ARM/cmp-bool.ll b/llvm/test/CodeGen/ARM/cmp-bool.ll --- a/llvm/test/CodeGen/ARM/cmp-bool.ll +++ b/llvm/test/CodeGen/ARM/cmp-bool.ll @@ -41,17 +41,15 @@ define void @bool_ne(i1 zeroext %a, i1 zeroext %b, void ()* nocapture %c) nounwind { ; ARM-LABEL: bool_ne: ; ARM: @ %bb.0: @ %entry -; ARM-NEXT: eor r0, r0, r1 -; ARM-NEXT: cmp r0, #1 -; ARM-NEXT: bxne lr +; ARM-NEXT: cmp r0, r1 +; ARM-NEXT: bxeq lr ; ARM-NEXT: bx r2 ; ; THUMB-LABEL: bool_ne: ; THUMB: @ %bb.0: @ %entry ; THUMB-NEXT: push {r7, lr} -; THUMB-NEXT: eors r0, r1 -; THUMB-NEXT: cmp r0, #1 -; THUMB-NEXT: bne .LBB1_2 +; THUMB-NEXT: cmp r0, r1 +; THUMB-NEXT: beq .LBB1_2 ; THUMB-NEXT: @ %bb.1: @ %if.then ; THUMB-NEXT: blx r2 ; THUMB-NEXT: .LBB1_2: @ %if.end @@ -59,10 +57,9 @@ ; ; THUMB2-LABEL: bool_ne: ; THUMB2: @ %bb.0: @ %entry -; THUMB2-NEXT: eors r0, r1 -; THUMB2-NEXT: cmp r0, #1 -; THUMB2-NEXT: it ne -; THUMB2-NEXT: bxne lr +; THUMB2-NEXT: cmp r0, r1 +; THUMB2-NEXT: it eq +; THUMB2-NEXT: bxeq lr ; THUMB2-NEXT: bx r2 entry: %cmp = xor i1 %a, %b diff --git a/llvm/test/CodeGen/RISCV/cmp-bool.ll b/llvm/test/CodeGen/RISCV/cmp-bool.ll --- a/llvm/test/CodeGen/RISCV/cmp-bool.ll +++ b/llvm/test/CodeGen/RISCV/cmp-bool.ll @@ -33,9 +33,7 @@ define void @bool_ne(i1 zeroext %a, i1 zeroext %b, void ()* nocapture %c) nounwind { ; RV32-LABEL: bool_ne: ; RV32: # %bb.0: # %entry -; RV32-NEXT: xor a0, a0, a1 -; RV32-NEXT: addi a1, zero, 1 -; RV32-NEXT: bne a0, a1, .LBB1_2 +; RV32-NEXT: beq a0, a1, .LBB1_2 ; RV32-NEXT: # %bb.1: # %if.then ; RV32-NEXT: jr a2 ; RV32-NEXT: .LBB1_2: # %if.end @@ -43,9 +41,7 @@ ; ; RV64-LABEL: bool_ne: ; RV64: # %bb.0: # %entry -; RV64-NEXT: xor a0, a0, a1 -; RV64-NEXT: addi a1, zero, 1 -; RV64-NEXT: bne a0, a1, .LBB1_2 +; RV64-NEXT: beq a0, a1, .LBB1_2 ; RV64-NEXT: # %bb.1: # %if.then ; RV64-NEXT: jr a2 ; RV64-NEXT: .LBB1_2: # %if.end diff --git a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll --- a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll +++ b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll @@ -112,16 +112,14 @@ ; CHECK-NEXT: i32.const $push[[L11:[0-9]+]]=, 2{{$}} ; CHECK-NEXT: i32.lt_s $push[[L4:[0-9]+]]=, $3, $pop[[L11]]{{$}} ; CHECK-NEXT: i32.xor $push[[L6:[0-9]+]]=, $pop[[L3]], $pop[[L4]]{{$}} -; CHECK-NEXT: i32.xor $push[[L7:[0-9]+]]=, $pop[[L5]], $pop[[L6]]{{$}} -; CHECK-NEXT: i32.const $push10=, 1{{$}} -; CHECK-NEXT: i32.ne $push8=, $pop7, $pop10{{$}} -; CHECK-NEXT: br_if 0, $pop8{{$}} -; CHECK-NEXT: i32.const $push9=, 0{{$}} -; CHECK-NEXT: return $pop9{{$}} +; CHECK-NEXT: i32.eq $push7=, $pop[[L5]], $pop[[L6]]{{$}} +; CHECK-NEXT: br_if 0, $pop7{{$}} +; CHECK-NEXT: i32.const $push8=, 0{{$}} +; CHECK-NEXT: return $pop8{{$}} ; CHECK-NEXT: .LBB{{[0-9]+}}_2: ; CHECK-NEXT: end_block{{$}} -; CHECK-NEXT: i32.const $push14=, 1{{$}} -; CHECK-NEXT: return $pop14{{$}} +; CHECK-NEXT: i32.const $push12=, 1{{$}} +; CHECK-NEXT: return $pop12{{$}} ; NOREGS-LABEL: stack_uses: ; NOREGS: .functype stack_uses (i32, i32, i32, i32) -> (i32){{$}} ; NOREGS-NEXT: block {{$}} @@ -139,9 +137,7 @@ ; NOREGS-NEXT: i32.const 2{{$}} ; NOREGS-NEXT: i32.lt_s ; NOREGS-NEXT: i32.xor {{$}} -; NOREGS-NEXT: i32.xor {{$}} -; NOREGS-NEXT: i32.const 1{{$}} -; NOREGS-NEXT: i32.ne {{$}} +; NOREGS-NEXT: i32.eq {{$}} ; NOREGS-NEXT: br_if 0{{$}} ; NOREGS-NEXT: i32.const 0{{$}} ; NOREGS-NEXT: return{{$}} diff --git a/llvm/test/CodeGen/X86/cmp-bool.ll b/llvm/test/CodeGen/X86/cmp-bool.ll --- a/llvm/test/CodeGen/X86/cmp-bool.ll +++ b/llvm/test/CodeGen/X86/cmp-bool.ll @@ -25,9 +25,8 @@ define void @bool_ne(i1 zeroext %a, i1 zeroext %b, void ()* nocapture %c) nounwind { ; CHECK-LABEL: bool_ne: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %esi, %edi -; CHECK-NEXT: cmpb $1, %dil -; CHECK-NEXT: jne .LBB1_1 +; CHECK-NEXT: cmpb %sil, %dil +; CHECK-NEXT: je .LBB1_1 ; CHECK-NEXT: # %bb.2: # %if.then ; CHECK-NEXT: jmpq *%rdx # TAILCALL ; CHECK-NEXT: .LBB1_1: # %if.end