[llvm] 0ef7cbc - [InstCombine] reduce compare of signbits of 2 values, signed variant
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 26 05:58:59 PST 2023
Author: Sanjay Patel
Date: 2023-01-26T08:58:45-05:00
New Revision: 0ef7cbc319ee6488a47fda1b45b0d7170722df31
URL: https://github.com/llvm/llvm-project/commit/0ef7cbc319ee6488a47fda1b45b0d7170722df31
DIFF: https://github.com/llvm/llvm-project/commit/0ef7cbc319ee6488a47fda1b45b0d7170722df31.diff
LOG: [InstCombine] reduce compare of signbits of 2 values, signed variant
(X s>> BitWidth - 1) == sext (Y s> -1) --> (X ^ Y) < 0
(X s>> BitWidth - 1) != sext (Y s> -1) --> (X ^ Y) > -1
This is the same logic as:
7cbfc39c77ca
...extended to deal with "signed" cast+shift instructions.
https://alive2.llvm.org/ce/z/LLidya
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/icmp-shr.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 1480a0ff9e2f..8e90014d24d8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4661,20 +4661,34 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
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
diff erent 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
diff erent 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);
+ }
}
}
diff --git a/llvm/test/Transforms/InstCombine/icmp-shr.ll b/llvm/test/Transforms/InstCombine/icmp-shr.ll
index 0259e601fafa..f4dfa2edfa17 100644
--- a/llvm/test/Transforms/InstCombine/icmp-shr.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-shr.ll
@@ -1465,10 +1465,8 @@ define i1 @exactly_one_set_signbit_wrong_pred(i8 %x, i8 %y) {
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
@@ -1482,9 +1480,8 @@ define i1 @exactly_one_set_signbit_use1_signed(i8 %x, i8 %y) {
; 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
@@ -1497,10 +1494,8 @@ define i1 @exactly_one_set_signbit_use1_signed(i8 %x, i8 %y) {
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>
@@ -1512,11 +1507,11 @@ define <2 x i1> @same_signbit_signed(<2 x i8> %x, <2 x i8> %y) {
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
@@ -1527,6 +1522,8 @@ define i1 @same_signbit_use2_signed(i8 %x, i8 %y) {
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
@@ -1548,10 +1545,8 @@ define i1 @same_signbit_use3_signed(i8 %x, i8 %y) {
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>
@@ -1561,6 +1556,8 @@ define <2 x i1> @same_signbit_poison_elts_signed(<2 x i8> %x, <2 x i8> %y) {
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
@@ -1576,6 +1573,8 @@ define i1 @same_signbit_wrong_type_signed(i8 %x, i32 %y) {
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
More information about the llvm-commits
mailing list