Type *SrcTy = X->getType();
unsigned DstBits = Trunc->getType()->getScalarSizeInBits(),
SrcBits = SrcTy->getScalarSizeInBits();
+
+ // (trunc (1 << Y) to iN) == 0 --> Y u>= N
+ // (trunc (1 << Y) to iN) != 0 --> Y u< N
+ // TODO: Handle any shifted constant by subtracting trailing zeros.
+ // TODO: Handle non-equality predicates.
+ // TODO: Handle compare to power-of-2 (non-zero) constant.
+ Value *Y;
+ if (Cmp.isEquality() && C.isZero() && match(X, m_Shl(m_One(), m_Value(Y)))) {
+ auto NewPred = Pred == Cmp.ICMP_EQ ? Cmp.ICMP_UGE : Cmp.ICMP_ULT;
+ return new ICmpInst(NewPred, Y, ConstantInt::get(SrcTy, DstBits));
+ }
+
if (Cmp.isEquality() && Trunc->hasOneUse()) {
// Canonicalize to a mask and wider compare if the wide type is suitable:
// (trunc X to i8) == C --> (X & 0xff) == (zext C)
}
define i1 @shl1_trunc_eq0(i32 %a) {
-; DL64-LABEL: @shl1_trunc_eq0(
-; DL64-NEXT: [[R:%.*]] = icmp ugt i32 [[A:%.*]], 15
-; DL64-NEXT: ret i1 [[R]]
-;
-; DL8-LABEL: @shl1_trunc_eq0(
-; DL8-NEXT: [[SHL:%.*]] = shl i32 1, [[A:%.*]]
-; DL8-NEXT: [[T:%.*]] = trunc i32 [[SHL]] to i16
-; DL8-NEXT: [[R:%.*]] = icmp eq i16 [[T]], 0
-; DL8-NEXT: ret i1 [[R]]
+; CHECK-LABEL: @shl1_trunc_eq0(
+; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[A:%.*]], 15
+; CHECK-NEXT: ret i1 [[R]]
;
%shl = shl i32 1, %a
%t = trunc i32 %shl to i16
define <2 x i1> @shl1_trunc_ne0(<2 x i8> %a) {
; CHECK-LABEL: @shl1_trunc_ne0(
-; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i8> <i8 1, i8 poison>, [[A:%.*]]
-; CHECK-NEXT: [[T:%.*]] = trunc <2 x i8> [[SHL]] to <2 x i5>
-; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i5> [[T]], zeroinitializer
+; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[A:%.*]], <i8 5, i8 5>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%shl = shl <2 x i8> <i8 1, i8 poison>, %a
; CHECK-NEXT: [[SHL:%.*]] = shl i37 1, [[A:%.*]]
; CHECK-NEXT: [[T:%.*]] = trunc i37 [[SHL]] to i8
; CHECK-NEXT: call void @use(i8 [[T]])
-; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[T]], 0
+; CHECK-NEXT: [[R:%.*]] = icmp ult i37 [[A]], 8
; CHECK-NEXT: ret i1 [[R]]
;
%shl = shl i37 1, %a
ret i1 %r
}
+; TODO: A > 4
+
define i1 @shl2_trunc_eq0(i9 %a) {
; CHECK-LABEL: @shl2_trunc_eq0(
; CHECK-NEXT: [[SHL:%.*]] = shl i9 2, [[A:%.*]]
ret i1 %r
}
+; TODO: A < 5
+
define i1 @shl1_trunc_sgt0(i9 %a) {
; CHECK-LABEL: @shl1_trunc_sgt0(
; CHECK-NEXT: [[SHL:%.*]] = shl i9 1, [[A:%.*]]
ret i1 %r
}
+; TODO: A == 0
+
define i1 @shl1_trunc_eq1(i64 %a) {
; CHECK-LABEL: @shl1_trunc_eq1(
; CHECK-NEXT: [[SHL:%.*]] = shl i64 1, [[A:%.*]]
ret i1 %r
}
+; TODO: A != 5
+
define i1 @shl1_trunc_ne32(i8 %a) {
; CHECK-LABEL: @shl1_trunc_ne32(
; CHECK-NEXT: [[SHL:%.*]] = shl i8 1, [[A:%.*]]