ConstantInt::get(V->getType(), 1));
}
+ unsigned DstBits = Trunc->getType()->getScalarSizeInBits(),
+ SrcBits = X->getType()->getScalarSizeInBits();
if (Cmp.isEquality() && Trunc->hasOneUse()) {
// Simplify icmp eq (trunc x to i8), 42 -> icmp eq x, 42|highbits if all
// of the high bits truncated out of x are known.
- unsigned DstBits = Trunc->getType()->getScalarSizeInBits(),
- SrcBits = X->getType()->getScalarSizeInBits();
KnownBits Known = computeKnownBits(X, 0, &Cmp);
// If all the high bits are known, we can do this xform.
}
}
+ // Look through truncated right-shift of the sign-bit for a sign-bit check:
+ // trunc iN (ShOp >> ShAmtC) to i[N - ShAmtC] < 0 --> ShOp < 0
+ // trunc iN (ShOp >> ShAmtC) to i[N - ShAmtC] > -1 --> ShOp > -1
+ Value *ShOp;
+ const APInt *ShAmtC;
+ bool TrueIfSigned;
+ if (isSignBitCheck(Pred, C, TrueIfSigned) &&
+ match(X, m_Shr(m_Value(ShOp), m_APInt(ShAmtC))) &&
+ DstBits == SrcBits - ShAmtC->getZExtValue()) {
+ return TrueIfSigned
+ ? new ICmpInst(ICmpInst::ICMP_SLT, ShOp,
+ ConstantInt::getNullValue(X->getType()))
+ : new ICmpInst(ICmpInst::ICMP_SGT, ShOp,
+ ConstantInt::getAllOnesValue(X->getType()));
+ }
+
return nullptr;
}
define i1 @shift_trunc_signbit_test(i32 %x) {
; CHECK-LABEL: @shift_trunc_signbit_test(
-; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 24
-; CHECK-NEXT: [[TR:%.*]] = trunc i32 [[SH]] to i8
-; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[TR]], 0
+; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%sh = lshr i32 %x, 24
; CHECK-NEXT: store <2 x i17> [[SH]], <2 x i17>* [[P1:%.*]], align 8
; CHECK-NEXT: [[TR:%.*]] = trunc <2 x i17> [[SH]] to <2 x i13>
; CHECK-NEXT: store <2 x i13> [[TR]], <2 x i13>* [[P2:%.*]], align 4
-; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i13> [[TR]], <i13 -1, i13 -1>
+; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i17> [[X]], <i17 -1, i17 -1>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%sh = lshr <2 x i17> %x, <i17 4, i17 4>
ret <2 x i1> %r
}
+; negative test
+
define i1 @shift_trunc_wrong_shift(i32 %x) {
; CHECK-LABEL: @shift_trunc_wrong_shift(
; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 23
ret i1 %r
}
+; negative test
+
define i1 @shift_trunc_wrong_cmp(i32 %x) {
; CHECK-LABEL: @shift_trunc_wrong_cmp(
; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X:%.*]], 24