Skip to content

Commit 21d3871

Browse files
committed
[InstCombine] fold not-shift of signbit to icmp+zext, part 2
Follow-up to: 6c39a3a That converted a pattern with ashr directly to icmp+zext, and this updates the pattern that we used to convert to. This canonicalizes to icmp for better analysis in the minimum case and shortens patterns where the source type is not the same as dest type: https://alive2.llvm.org/ce/z/tpXJ64 https://alive2.llvm.org/ce/z/dQ405O This requires an adjustment to an icmp transform to avoid infinite looping.
1 parent 310eea1 commit 21d3871

File tree

8 files changed

+35
-29
lines changed

8 files changed

+35
-29
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1027,8 +1027,11 @@ Instruction *InstCombinerImpl::transformZExtICmp(ICmpInst *Cmp, ZExtInst &Zext)
10271027
// If Op1C some other power of two, convert:
10281028
KnownBits Known = computeKnownBits(Cmp->getOperand(0), 0, &Zext);
10291029

1030+
// Exactly 1 possible 1? But not the high-bit because that is
1031+
// canonicalized to this form.
10301032
APInt KnownZeroMask(~Known.Zero);
1031-
if (KnownZeroMask.isPowerOf2()) { // Exactly 1 possible 1?
1033+
if (KnownZeroMask.isPowerOf2() &&
1034+
(Zext.getType()->getScalarSizeInBits() != KnownZeroMask.logBase2() + 1)) {
10321035
bool isNE = Cmp->getPredicate() == ICmpInst::ICMP_NE;
10331036
uint32_t ShAmt = KnownZeroMask.logBase2();
10341037
Value *In = Cmp->getOperand(0);

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,10 +1091,17 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
10911091

10921092
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
10931093
Type *Ty = I.getType();
1094+
Value *X;
10941095
const APInt *C;
1096+
unsigned BitWidth = Ty->getScalarSizeInBits();
1097+
1098+
// (iN (~X) u>> (N - 1)) --> zext (X > -1)
1099+
if (match(Op0, m_OneUse(m_Not(m_Value(X)))) &&
1100+
match(Op1, m_SpecificIntAllowUndef(BitWidth - 1)))
1101+
return new ZExtInst(Builder.CreateIsNotNeg(X, "isnotneg"), Ty);
1102+
10951103
if (match(Op1, m_APInt(C))) {
10961104
unsigned ShAmtC = C->getZExtValue();
1097-
unsigned BitWidth = Ty->getScalarSizeInBits();
10981105
auto *II = dyn_cast<IntrinsicInst>(Op0);
10991106
if (II && isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == ShAmtC &&
11001107
(II->getIntrinsicID() == Intrinsic::ctlz ||
@@ -1320,7 +1327,6 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
13201327
}
13211328

13221329
// Transform (x << y) >> y to x & (-1 >> y)
1323-
Value *X;
13241330
if (match(Op0, m_OneUse(m_Shl(m_Value(X), m_Specific(Op1))))) {
13251331
Constant *AllOnes = ConstantInt::getAllOnesValue(Ty);
13261332
Value *Mask = Builder.CreateLShr(AllOnes, Op1);

llvm/test/Transforms/InstCombine/and-xor-merge.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ define i32 @test2(i32 %x, i32 %y, i32 %z) {
2828

2929
define i32 @PR38781(i32 %a, i32 %b) {
3030
; CHECK-LABEL: @PR38781(
31-
; CHECK-NEXT: [[B_LOBIT_NOT1_DEMORGAN:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
32-
; CHECK-NEXT: [[B_LOBIT_NOT1:%.*]] = xor i32 [[B_LOBIT_NOT1_DEMORGAN]], -1
33-
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[B_LOBIT_NOT1]], 31
31+
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
32+
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], -1
33+
; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP2]] to i32
3434
; CHECK-NEXT: ret i32 [[AND]]
3535
;
3636
%a.lobit = lshr i32 %a, 31

llvm/test/Transforms/InstCombine/icmp-mul-zext.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ define i32 @sterix(i32, i8, i64) {
1919
; CHECK-NEXT: [[AND:%.*]] = and i64 [[MUL3]], [[TMP2]]
2020
; CHECK-NEXT: [[CONV4:%.*]] = trunc i64 [[AND]] to i32
2121
; CHECK-NEXT: [[TOBOOL7_NOT:%.*]] = icmp eq i32 [[CONV4]], 0
22-
; CHECK-NEXT: [[PHITMP:%.*]] = zext i1 [[TOBOOL7_NOT]] to i32
22+
; CHECK-NEXT: [[PHI_CAST:%.*]] = zext i1 [[TOBOOL7_NOT]] to i32
2323
; CHECK-NEXT: br label [[LOR_END]]
2424
; CHECK: lor.end:
25-
; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHITMP]], [[LOR_RHS]] ]
25+
; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHI_CAST]], [[LOR_RHS]] ]
2626
; CHECK-NEXT: ret i32 [[TMP4]]
2727
;
2828
entry:

llvm/test/Transforms/InstCombine/lshr.ll

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -947,8 +947,8 @@ define i32 @not_narrow_bswap(i24 %x) {
947947

948948
define i8 @not_signbit(i8 %x) {
949949
; CHECK-LABEL: @not_signbit(
950-
; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1
951-
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 7
950+
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
951+
; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8
952952
; CHECK-NEXT: ret i8 [[R]]
953953
;
954954
%a = xor i8 %x, -1
@@ -958,8 +958,8 @@ define i8 @not_signbit(i8 %x) {
958958

959959
define <2 x i6> @not_signbit_vec(<2 x i6> %x) {
960960
; CHECK-LABEL: @not_signbit_vec(
961-
; CHECK-NEXT: [[A:%.*]] = xor <2 x i6> [[X:%.*]], <i6 -1, i6 poison>
962-
; CHECK-NEXT: [[R:%.*]] = lshr <2 x i6> [[A]], <i6 5, i6 poison>
961+
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i6> [[X:%.*]], <i6 -1, i6 -1>
962+
; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i6>
963963
; CHECK-NEXT: ret <2 x i6> [[R]]
964964
;
965965
%a = xor <2 x i6> %x, <i6 -1, i6 poison>
@@ -969,8 +969,8 @@ define <2 x i6> @not_signbit_vec(<2 x i6> %x) {
969969

970970
define i8 @not_signbit_alt_xor(i8 %x) {
971971
; CHECK-LABEL: @not_signbit_alt_xor(
972-
; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1
973-
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 7
972+
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
973+
; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8
974974
; CHECK-NEXT: ret i8 [[R]]
975975
;
976976
%a = xor i8 %x, -2
@@ -1004,9 +1004,8 @@ define i32 @not_signbit_use(i32 %x) {
10041004

10051005
define i32 @not_signbit_zext(i16 %x) {
10061006
; CHECK-LABEL: @not_signbit_zext(
1007-
; CHECK-NEXT: [[A:%.*]] = xor i16 [[X:%.*]], -1
1008-
; CHECK-NEXT: [[R:%.*]] = lshr i16 [[A]], 15
1009-
; CHECK-NEXT: [[R2:%.*]] = zext i16 [[R]] to i32
1007+
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1
1008+
; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i32
10101009
; CHECK-NEXT: ret i32 [[R2]]
10111010
;
10121011
%a = xor i16 %x, -1
@@ -1017,9 +1016,8 @@ define i32 @not_signbit_zext(i16 %x) {
10171016

10181017
define i8 @not_signbit_trunc(i16 %x) {
10191018
; CHECK-LABEL: @not_signbit_trunc(
1020-
; CHECK-NEXT: [[A:%.*]] = xor i16 [[X:%.*]], -1
1021-
; CHECK-NEXT: [[R:%.*]] = lshr i16 [[A]], 15
1022-
; CHECK-NEXT: [[R2:%.*]] = trunc i16 [[R]] to i8
1019+
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1
1020+
; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i8
10231021
; CHECK-NEXT: ret i8 [[R2]]
10241022
;
10251023
%a = xor i16 %x, -1

llvm/test/Transforms/InstCombine/negated-bitmask.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,8 @@ define i8 @neg_signbit_use2(i5 %x) {
233233

234234
define i32 @neg_not_signbit1(i8 %x) {
235235
; CHECK-LABEL: @neg_not_signbit1(
236-
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], -1
237-
; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], 7
238-
; CHECK-NEXT: [[R:%.*]] = zext i8 [[TMP2]] to i32
236+
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
237+
; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i32
239238
; CHECK-NEXT: ret i32 [[R]]
240239
;
241240
%s = lshr i8 %x, 7

llvm/test/Transforms/InstCombine/xor.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,8 +1061,8 @@ define i8 @not_lshr(i8 %x) {
10611061

10621062
define <2 x i8> @not_lshr_vec(<2 x i8> %x) {
10631063
; CHECK-LABEL: @not_lshr_vec(
1064-
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
1065-
; CHECK-NEXT: [[R:%.*]] = lshr <2 x i8> [[TMP1]], <i8 7, i8 7>
1064+
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
1065+
; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i8>
10661066
; CHECK-NEXT: ret <2 x i8> [[R]]
10671067
;
10681068
%a = lshr <2 x i8> %x, <i8 7, i8 7>

llvm/test/Transforms/InstCombine/zext.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,10 +501,10 @@ define i8 @notneg_zext_narrower_use(i32 %x) {
501501

502502
define i8 @disguised_signbit_clear_test(i64 %x) {
503503
; CHECK-LABEL: @disguised_signbit_clear_test(
504-
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i8
505-
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[TMP1]], -1
506-
; CHECK-NEXT: [[TMP3:%.*]] = lshr i8 [[TMP2]], 7
507-
; CHECK-NEXT: ret i8 [[TMP3]]
504+
; CHECK-NEXT: [[A1:%.*]] = and i64 [[X:%.*]], 128
505+
; CHECK-NEXT: [[T4:%.*]] = icmp eq i64 [[A1]], 0
506+
; CHECK-NEXT: [[T6:%.*]] = zext i1 [[T4]] to i8
507+
; CHECK-NEXT: ret i8 [[T6]]
508508
;
509509
%a1 = and i64 %x, 128
510510
%t4 = icmp eq i64 %a1, 0

0 commit comments

Comments
 (0)