if (Instruction *I = foldICmpAndConstConst(Cmp, And, C))
return I;
+ const ICmpInst::Predicate Pred = Cmp.getPredicate();
+ bool TrueIfNeg;
+ if (isSignBitCheck(Pred, C, TrueIfNeg)) {
+ // ((X - 1) & ~X) < 0 --> X == 0
+ // ((X - 1) & ~X) >= 0 --> X != 0
+ Value *X;
+ if (match(And->getOperand(0), m_Add(m_Value(X), m_AllOnes())) &&
+ match(And->getOperand(1), m_Not(m_Specific(X)))) {
+ auto NewPred = TrueIfNeg ? CmpInst::ICMP_EQ : CmpInst::ICMP_NE;
+ return new ICmpInst(NewPred, X, ConstantInt::getNullValue(X->getType()));
+ }
+ }
+
// TODO: These all require that Y is constant too, so refactor with the above.
// Try to optimize things like "A[i] & 42 == 0" to index computations.
// X & -C != -C -> X <= u ~C
// iff C is a power of 2
if (Cmp.getOperand(1) == Y && (-C).isPowerOf2()) {
- auto NewPred = Cmp.getPredicate() == CmpInst::ICMP_EQ ? CmpInst::ICMP_UGT
- : CmpInst::ICMP_ULE;
+ auto NewPred =
+ Pred == CmpInst::ICMP_EQ ? CmpInst::ICMP_UGT : CmpInst::ICMP_ULE;
return new ICmpInst(NewPred, X, SubOne(cast<Constant>(Cmp.getOperand(1))));
}
if (auto *AndVTy = dyn_cast<VectorType>(And->getType()))
NTy = VectorType::get(NTy, AndVTy->getElementCount());
Value *Trunc = Builder.CreateTrunc(X, NTy);
- auto NewPred = Cmp.getPredicate() == CmpInst::ICMP_EQ ? CmpInst::ICMP_SGE
- : CmpInst::ICMP_SLT;
+ auto NewPred =
+ Pred == CmpInst::ICMP_EQ ? CmpInst::ICMP_SGE : CmpInst::ICMP_SLT;
return new ICmpInst(NewPred, Trunc, Constant::getNullValue(NTy));
}
}
define i1 @signbit_true_logic(i8 %x) {
; CHECK-LABEL: @signbit_true_logic(
-; CHECK-NEXT: [[DEC:%.*]] = add i8 [[X:%.*]], -1
-; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[X]], -1
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[DEC]], [[NOT]]
-; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[AND]], 0
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%dec = add i8 %x, -1
define <2 x i1> @signbit_false_logic(<2 x i5> %x) {
; CHECK-LABEL: @signbit_false_logic(
-; CHECK-NEXT: [[DEC:%.*]] = add <2 x i5> [[X:%.*]], <i5 -1, i5 undef>
-; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i5> [[X]], <i5 -1, i5 -1>
-; CHECK-NEXT: [[AND:%.*]] = and <2 x i5> [[DEC]], [[NOT]]
-; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i5> [[AND]], <i5 -1, i5 -1>
+; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i5> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%dec = add <2 x i5> %x, <i5 -1, i5 undef>
; CHECK-NEXT: call void @use_i64(i64 [[NOT]])
; CHECK-NEXT: [[AND:%.*]] = and i64 [[DEC]], [[NOT]]
; CHECK-NEXT: call void @use_i64(i64 [[AND]])
-; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[AND]], 0
+; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%dec = add i64 %x, -1