Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2486,8 +2486,20 @@ ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate(); Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1); Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1); + PointerType *LHS0PtrTy = dyn_cast(LHS0->getType()); if ((LHS->hasOneUse() || RHS->hasOneUse()) && - LHS0->getType() == RHS0->getType()) { + LHS0->getType() == RHS0->getType() && + !(LHS0PtrTy && LHS0PtrTy->getElementType()->isVectorTy())) { + if (!LHS0->getType()->isIntOrIntVectorTy()) { + assert(LHS0->getType()->isPointerTy() && RHS0->getType()->isPointerTy() && + "expected ptrs"); + Type *PtrIntTy = DL.getIntPtrType(LHS0->getType()); + LHS0 = Builder.CreatePtrToInt(LHS0, PtrIntTy); + LHS1 = Builder.CreatePtrToInt(LHS1, PtrIntTy); + RHS0 = Builder.CreatePtrToInt(RHS0, PtrIntTy); + RHS1 = Builder.CreatePtrToInt(RHS1, PtrIntTy); + } + // (X > -1) ^ (Y > -1) --> (X ^ Y) < 0 // (X < 0) ^ (Y < 0) --> (X ^ Y) < 0 if ((PredL == CmpInst::ICMP_SGT && match(LHS1, m_AllOnes()) && Index: test/Transforms/InstCombine/xor-icmps.ll =================================================================== --- test/Transforms/InstCombine/xor-icmps.ll +++ test/Transforms/InstCombine/xor-icmps.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" define i1 @eq_zero(i4 %x, i4 %y) { ; CHECK-LABEL: @eq_zero( @@ -158,3 +159,29 @@ ret i1 %E } +define i1 @xor_icmp_ptr(i8* %c, i8* %d) { +; CHECK-LABEL: @xor_icmp_ptr( +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i8* [[C:%.*]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint i8* [[D:%.*]] to i64 +; CHECK-NEXT: [[TMP3:%.*]] = xor i64 [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0 +; CHECK-NEXT: ret i1 [[TMP4]] +; + %cmp = icmp slt i8* %c, null + %cmp1 = icmp slt i8* %d, null + %xor = xor i1 %cmp, %cmp1 + ret i1 %xor +} + +define i1 @xor_icmp_ptr_vec(<4 x i32>* %c, <4 x i32>* %d) { +; CHECK-LABEL: @xor_icmp_ptr_vec( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <4 x i32>* [[C:%.*]], null +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <4 x i32>* [[D:%.*]], null +; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[CMP]], [[CMP1]] +; CHECK-NEXT: ret i1 [[XOR]] +; + %cmp = icmp slt <4 x i32>* %c, null + %cmp1 = icmp slt <4 x i32>* %d, null + %xor = xor i1 %cmp, %cmp1 + ret i1 %xor +}