Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -1608,6 +1608,21 @@ } } + // The compares may be hidden behind zexts. + // Look for this pattern: zext(icmp X, C0) & zext(icmp X, C1)). + ICmpInst::Predicate Pred0, Pred1; + const APInt *C0, *C1; + Value *X; + if (match(Op0, m_ZExt(m_ICmp(Pred0, m_Value(X), m_APInt(C0)))) && + match(Op1, m_ZExt(m_ICmp(Pred1, m_Specific(X), m_APInt(C1))))) { + // Make a constant range that's the intersection of the two icmp ranges. + // If the intersection is empty, we know that the result is false. + auto Range0 = ConstantRange::makeAllowedICmpRegion(Pred0, *C0); + auto Range1 = ConstantRange::makeAllowedICmpRegion(Pred1, *C1); + if (Range0.intersectWith(Range1).isEmptySet()) + return Constant::getNullValue(Op0->getType()); + } + // Try some generic simplifications for associative operations. if (Value *V = SimplifyAssociativeBinOp(Instruction::And, Op0, Op1, Q, MaxRecurse)) Index: test/Transforms/InstSimplify/AndOrXor.ll =================================================================== --- test/Transforms/InstSimplify/AndOrXor.ll +++ test/Transforms/InstSimplify/AndOrXor.ll @@ -233,12 +233,7 @@ define i32 @and_of_zexted_icmps(i32 %i) { ; CHECK-LABEL: @and_of_zexted_icmps( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 %i, 0 -; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 %i, 4 -; CHECK-NEXT: [[CONV2:%.*]] = zext i1 [[CMP1]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV]], [[CONV2]] -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: ret i32 0 ; %cmp = icmp eq i32 %i, 0 %conv = zext i1 %cmp to i32 @@ -250,12 +245,7 @@ define <4 x i32> @and_of_zexted_icmps_vec(<4 x i32> %i) { ; CHECK-LABEL: @and_of_zexted_icmps_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <4 x i32> %i, zeroinitializer -; CHECK-NEXT: [[CONV:%.*]] = zext <4 x i1> [[CMP]] to <4 x i32> -; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <4 x i32> %i, zeroinitializer -; CHECK-NEXT: [[CONV2:%.*]] = zext <4 x i1> [[CMP1]] to <4 x i32> -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[CONV]], [[CONV2]] -; CHECK-NEXT: ret <4 x i32> [[AND]] +; CHECK-NEXT: ret <4 x i32> zeroinitializer ; %cmp = icmp eq <4 x i32> %i, zeroinitializer %conv = zext <4 x i1> %cmp to <4 x i32>