Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2898,6 +2898,17 @@ return SelectInst::Create( Builder.CreateICmp(getInverseMinMaxPred(SPF), NotX, Y), NotX, Y); } + + // If both sides are freely invertible, then we can get rid of the xor + // completelely + if (IsFreeToInvert(LHS, !LHS->hasNUsesOrMore(3)) && + IsFreeToInvert(RHS, !RHS->hasNUsesOrMore(3))) { + Value *NotLHS = Builder.CreateNot(LHS); + Value *NotRHS = Builder.CreateNot(RHS); + return SelectInst::Create( + Builder.CreateICmp(getInverseMinMaxPred(SPF), NotLHS, NotRHS), + NotLHS, NotRHS); + } } } Index: test/Transforms/InstCombine/xor.ll =================================================================== --- test/Transforms/InstCombine/xor.ll +++ test/Transforms/InstCombine/xor.ll @@ -802,3 +802,31 @@ %res = mul i32 %umin, %add ret i32 %res } + +define i32 @test48(i32 %x) { +; CHECK-LABEL: @test48( +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], -1 +; CHECK-NEXT: [[D:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 -1 +; CHECK-NEXT: ret i32 [[D]] +; + %a = sub i32 -2, %x + %b = icmp sgt i32 %a, -1 + %c = select i1 %b, i32 %a, i32 0 + %d = xor i32 %c, -1 + ret i32 %d +} + +define i32 @test49(i32 %x) { +; CHECK-LABEL: @test49( +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], 0 +; CHECK-NEXT: [[D:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 0 +; CHECK-NEXT: ret i32 [[D]] +; + %a = sub i32 -2, %x + %b = icmp slt i32 %a, 0 + %c = select i1 %b, i32 %a, i32 -1 + %d = xor i32 %c, -1 + ret i32 %d +}