Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -4253,11 +4253,21 @@ return RepOp; // We cannot replace a constant, and shouldn't even try. - if (isa(Op)) + if (isa(Op) || !isa(V)) return nullptr; - auto *I = dyn_cast(V); - if (!I || !is_contained(I->operands(), Op)) + auto *I = cast(V); + if (I->getOpcode() == Instruction::Xor && !is_contained(I->operands(), Op)) { + Value *S = simplifyWithOpReplaced(I->getOperand(0), Op, RepOp, Q, + AllowRefinement, MaxRecurse); + if (!S) + return nullptr; + Constant *Cst = dyn_cast(S); + if (Cst && Cst->isNullValue()) + return I->getOperand(1); + } + + if (!is_contained(I->operands(), Op)) return nullptr; // The arguments of a phi node might refer to a value from a previous Index: llvm/test/Transforms/InstCombine/select-cmp.ll =================================================================== --- llvm/test/Transforms/InstCombine/select-cmp.ll +++ llvm/test/Transforms/InstCombine/select-cmp.ll @@ -345,4 +345,18 @@ ret i1 %r } +; https://alive2.llvm.org/ce/z/TGgJTq +define i32 @select_icmp_xor_multi_insn(i32 noundef %a, i32 noundef %b) { +; CHECK-LABEL: @select_icmp_xor_multi_insn( +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[XOR1]] +; + %tobool = icmp eq i32 %a, %b + %not = xor i32 %a, -1 + %xor1 = xor i32 %not, %b + %cond = select i1 %tobool, i32 -1, i32 %xor1 + ret i32 %cond +} + declare void @use(i1)