}
}
+// Transform pattern like:
+// (1 << Y) u<= X
+// (1 << Y) u> X
+// Into:
+// (X l>> Y) != 0
+// (X l>> Y) == 0
+static Instruction *foldICmpWithHighBitMask(ICmpInst &Cmp,
+ InstCombiner::BuilderTy &Builder) {
+ ICmpInst::Predicate Pred;
+ Value *X, *Y;
+ if (!match(&Cmp,
+ m_c_ICmp(Pred, m_OneUse(m_Shl(m_One(), m_Value(Y))), m_Value(X))))
+ return nullptr;
+
+ // We want X to be the icmp's second operand, so swap predicate if it is not.
+ if (Cmp.getOperand(0) == X)
+ Pred = Cmp.getSwappedPredicate();
+
+ ICmpInst::Predicate NewPred;
+ switch (Pred) {
+ case ICmpInst::ICMP_ULE:
+ NewPred = ICmpInst::ICMP_NE;
+ break;
+ case ICmpInst::ICMP_UGT:
+ NewPred = ICmpInst::ICMP_EQ;
+ break;
+ default:
+ return nullptr;
+ }
+
+ Value *NewX = Builder.CreateLShr(X, Y, X->getName() + ".highbits");
+ Constant *Zero = Constant::getNullValue(NewX->getType());
+ return CmpInst::Create(Instruction::ICmp, NewPred, NewX, Zero);
+}
+
static Instruction *foldVectorCmp(CmpInst &Cmp,
InstCombiner::BuilderTy &Builder) {
// If both arguments of the cmp are shuffles that use the same mask and
return foldICmpAddOpConst(X, *C, I.getSwappedPredicate());
}
+ if (Instruction *Res = foldICmpWithHighBitMask(I, Builder))
+ return Res;
+
if (I.getType()->isVectorTy())
if (Instruction *Res = foldVectorCmp(I, Builder))
return Res;
define i1 @p0(i8 %val, i8 %bits) {
; CHECK-LABEL: @p0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T0]], [[VAL:%.*]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits
define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
; CHECK-LABEL: @p1_vec(
-; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[T0]], [[VAL:%.*]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%t0 = shl <2 x i8> <i8 1, i8 1>, %bits
define <3 x i1> @p2_vec_undef(<3 x i8> %val, <3 x i8> %bits) {
; CHECK-LABEL: @p2_vec_undef(
-; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp ugt <3 x i8> [[T0]], [[VAL:%.*]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <3 x i1> [[R]]
;
%t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
define i1 @c0(i8 %bits) {
; CHECK-LABEL: @c0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
-; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[VAL]], [[T0]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits
define i1 @p0(i8 %val, i8 %bits) {
; CHECK-LABEL: @p0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[T0]], [[VAL:%.*]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits
define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
; CHECK-LABEL: @p1_vec(
-; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp ule <2 x i8> [[T0]], [[VAL:%.*]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%t0 = shl <2 x i8> <i8 1, i8 1>, %bits
define <3 x i1> @p2_vec_undef(<3 x i8> %val, <3 x i8> %bits) {
; CHECK-LABEL: @p2_vec_undef(
-; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp ule <3 x i8> [[T0]], [[VAL:%.*]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <3 x i1> [[R]]
;
%t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
define i1 @c0(i8 %bits) {
; CHECK-LABEL: @c0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
-; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[VAL]], [[T0]]
+; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits