if (match(Op0, m_And(m_Value(B), m_LowBitMask(MaskC))) &&
MaskC->countTrailingOnes() == A->getType()->getScalarSizeInBits())
return new ICmpInst(Pred, A, Builder.CreateTrunc(B, A->getType()));
+ }
- // Test if 2 values have different or same signbits:
- // (X u>> BitWidth - 1) == zext (Y s> -1) --> (X ^ Y) < 0
- // (X u>> BitWidth - 1) != zext (Y s> -1) --> (X ^ Y) > -1
+ // Test if 2 values have different or same signbits:
+ // (X u>> BitWidth - 1) == zext (Y s> -1) --> (X ^ Y) < 0
+ // (X u>> BitWidth - 1) != zext (Y s> -1) --> (X ^ Y) > -1
+ // (X s>> BitWidth - 1) == sext (Y s> -1) --> (X ^ Y) < 0
+ // (X s>> BitWidth - 1) != sext (Y s> -1) --> (X ^ Y) > -1
+ Instruction *ExtI;
+ if (match(Op1, m_CombineAnd(m_Instruction(ExtI), m_ZExtOrSExt(m_Value(A)))) &&
+ (Op0->hasOneUse() || Op1->hasOneUse())) {
unsigned OpWidth = Op0->getType()->getScalarSizeInBits();
+ Instruction *ShiftI;
Value *X, *Y;
ICmpInst::Predicate Pred2;
- if (match(Op0, m_LShr(m_Value(X), m_SpecificIntAllowUndef(OpWidth - 1))) &&
+ if (match(Op0, m_CombineAnd(m_Instruction(ShiftI),
+ m_Shr(m_Value(X),
+ m_SpecificIntAllowUndef(OpWidth - 1)))) &&
match(A, m_ICmp(Pred2, m_Value(Y), m_AllOnes())) &&
Pred2 == ICmpInst::ICMP_SGT && X->getType() == Y->getType()) {
- Value *Xor = Builder.CreateXor(X, Y, "xor.signbits");
- Value *R = (Pred == ICmpInst::ICMP_EQ) ? Builder.CreateIsNeg(Xor) :
- Builder.CreateIsNotNeg(Xor);
- return replaceInstUsesWith(I, R);
+ unsigned ExtOpc = ExtI->getOpcode();
+ unsigned ShiftOpc = ShiftI->getOpcode();
+ if ((ExtOpc == Instruction::ZExt && ShiftOpc == Instruction::LShr) ||
+ (ExtOpc == Instruction::SExt && ShiftOpc == Instruction::AShr)) {
+ Value *Xor = Builder.CreateXor(X, Y, "xor.signbits");
+ Value *R = (Pred == ICmpInst::ICMP_EQ) ? Builder.CreateIsNeg(Xor)
+ : Builder.CreateIsNotNeg(Xor);
+ return replaceInstUsesWith(I, R);
+ }
}
}
define i1 @exactly_one_set_signbit_signed(i8 %x, i8 %y) {
; CHECK-LABEL: @exactly_one_set_signbit_signed(
-; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 7
-; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i8 [[Y:%.*]], -1
-; CHECK-NEXT: [[YPOSZ:%.*]] = sext i1 [[YPOS]] to i8
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[XSIGN]], [[YPOSZ]]
+; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[XOR_SIGNBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%xsign = ashr i8 %x, 7
; CHECK-LABEL: @exactly_one_set_signbit_use1_signed(
; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 7
; CHECK-NEXT: call void @use(i8 [[XSIGN]])
-; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i8 [[Y:%.*]], -1
-; CHECK-NEXT: [[YPOSZ:%.*]] = sext i1 [[YPOS]] to i8
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[XSIGN]], [[YPOSZ]]
+; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[XOR_SIGNBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%xsign = ashr i8 %x, 7
define <2 x i1> @same_signbit_signed(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @same_signbit_signed(
-; CHECK-NEXT: [[XSIGN:%.*]] = ashr <2 x i8> [[X:%.*]], <i8 7, i8 7>
-; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt <2 x i8> [[Y:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT: [[YPOSZ:%.*]] = sext <2 x i1> [[YPOS]] to <2 x i8>
-; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[XSIGN]], [[YPOSZ]]
+; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[XOR_SIGNBITS]], <i8 -1, i8 -1>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%xsign = ashr <2 x i8> %x, <i8 7, i8 7>
define i1 @same_signbit_use2_signed(i8 %x, i8 %y) {
; CHECK-LABEL: @same_signbit_use2_signed(
-; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 7
; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YPOSZ:%.*]] = sext i1 [[YPOS]] to i8
; CHECK-NEXT: call void @use(i8 [[YPOSZ]])
-; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[XSIGN]], [[YPOSZ]]
+; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X:%.*]], [[Y]]
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[XOR_SIGNBITS]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%xsign = ashr i8 %x, 7
ret i1 %r
}
+; negative test
+
define i1 @same_signbit_use3_signed(i8 %x, i8 %y) {
; CHECK-LABEL: @same_signbit_use3_signed(
; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 7
define <2 x i1> @same_signbit_poison_elts_signed(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @same_signbit_poison_elts_signed(
-; CHECK-NEXT: [[XSIGN:%.*]] = ashr <2 x i8> [[X:%.*]], <i8 7, i8 poison>
-; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt <2 x i8> [[Y:%.*]], <i8 -1, i8 poison>
-; CHECK-NEXT: [[YPOSZ:%.*]] = sext <2 x i1> [[YPOS]] to <2 x i8>
-; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[XSIGN]], [[YPOSZ]]
+; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[XOR_SIGNBITS]], <i8 -1, i8 -1>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%xsign = ashr <2 x i8> %x, <i8 7, i8 poison>
ret <2 x i1> %r
}
+; negative test
+
define i1 @same_signbit_wrong_type_signed(i8 %x, i32 %y) {
; CHECK-LABEL: @same_signbit_wrong_type_signed(
; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 7
ret i1 %r
}
+; negative test
+
define i1 @exactly_one_set_signbit_wrong_shamt_signed(i8 %x, i8 %y) {
; CHECK-LABEL: @exactly_one_set_signbit_wrong_shamt_signed(
; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 6