Skip to content

Commit

Permalink
[InstCombine] fold not-shift of signbit to icmp+zext, part 2
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rotateright committed Jan 8, 2023
1 parent 310eea1 commit 21d3871
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 29 deletions.
5 changes: 4 additions & 1 deletion llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,8 +1027,11 @@ Instruction *InstCombinerImpl::transformZExtICmp(ICmpInst *Cmp, ZExtInst &Zext)
// If Op1C some other power of two, convert:
KnownBits Known = computeKnownBits(Cmp->getOperand(0), 0, &Zext);

// Exactly 1 possible 1? But not the high-bit because that is
// canonicalized to this form.
APInt KnownZeroMask(~Known.Zero);
if (KnownZeroMask.isPowerOf2()) { // Exactly 1 possible 1?
if (KnownZeroMask.isPowerOf2() &&
(Zext.getType()->getScalarSizeInBits() != KnownZeroMask.logBase2() + 1)) {
bool isNE = Cmp->getPredicate() == ICmpInst::ICMP_NE;
uint32_t ShAmt = KnownZeroMask.logBase2();
Value *In = Cmp->getOperand(0);
Expand Down
10 changes: 8 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1091,10 +1091,17 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {

Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
Type *Ty = I.getType();
Value *X;
const APInt *C;
unsigned BitWidth = Ty->getScalarSizeInBits();

// (iN (~X) u>> (N - 1)) --> zext (X > -1)
if (match(Op0, m_OneUse(m_Not(m_Value(X)))) &&
match(Op1, m_SpecificIntAllowUndef(BitWidth - 1)))
return new ZExtInst(Builder.CreateIsNotNeg(X, "isnotneg"), Ty);

if (match(Op1, m_APInt(C))) {
unsigned ShAmtC = C->getZExtValue();
unsigned BitWidth = Ty->getScalarSizeInBits();
auto *II = dyn_cast<IntrinsicInst>(Op0);
if (II && isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == ShAmtC &&
(II->getIntrinsicID() == Intrinsic::ctlz ||
Expand Down Expand Up @@ -1320,7 +1327,6 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
}

// Transform (x << y) >> y to x & (-1 >> y)
Value *X;
if (match(Op0, m_OneUse(m_Shl(m_Value(X), m_Specific(Op1))))) {
Constant *AllOnes = ConstantInt::getAllOnesValue(Ty);
Value *Mask = Builder.CreateLShr(AllOnes, Op1);
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/InstCombine/and-xor-merge.ll
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ define i32 @test2(i32 %x, i32 %y, i32 %z) {

define i32 @PR38781(i32 %a, i32 %b) {
; CHECK-LABEL: @PR38781(
; CHECK-NEXT: [[B_LOBIT_NOT1_DEMORGAN:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[B_LOBIT_NOT1:%.*]] = xor i32 [[B_LOBIT_NOT1_DEMORGAN]], -1
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[B_LOBIT_NOT1]], 31
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], -1
; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP2]] to i32
; CHECK-NEXT: ret i32 [[AND]]
;
%a.lobit = lshr i32 %a, 31
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/icmp-mul-zext.ll
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ define i32 @sterix(i32, i8, i64) {
; CHECK-NEXT: [[AND:%.*]] = and i64 [[MUL3]], [[TMP2]]
; CHECK-NEXT: [[CONV4:%.*]] = trunc i64 [[AND]] to i32
; CHECK-NEXT: [[TOBOOL7_NOT:%.*]] = icmp eq i32 [[CONV4]], 0
; CHECK-NEXT: [[PHITMP:%.*]] = zext i1 [[TOBOOL7_NOT]] to i32
; CHECK-NEXT: [[PHI_CAST:%.*]] = zext i1 [[TOBOOL7_NOT]] to i32
; CHECK-NEXT: br label [[LOR_END]]
; CHECK: lor.end:
; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHITMP]], [[LOR_RHS]] ]
; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHI_CAST]], [[LOR_RHS]] ]
; CHECK-NEXT: ret i32 [[TMP4]]
;
entry:
Expand Down
22 changes: 10 additions & 12 deletions llvm/test/Transforms/InstCombine/lshr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -947,8 +947,8 @@ define i32 @not_narrow_bswap(i24 %x) {

define i8 @not_signbit(i8 %x) {
; CHECK-LABEL: @not_signbit(
; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 7
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8
; CHECK-NEXT: ret i8 [[R]]
;
%a = xor i8 %x, -1
Expand All @@ -958,8 +958,8 @@ define i8 @not_signbit(i8 %x) {

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

define i8 @not_signbit_alt_xor(i8 %x) {
; CHECK-LABEL: @not_signbit_alt_xor(
; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 7
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8
; CHECK-NEXT: ret i8 [[R]]
;
%a = xor i8 %x, -2
Expand Down Expand Up @@ -1004,9 +1004,8 @@ define i32 @not_signbit_use(i32 %x) {

define i32 @not_signbit_zext(i16 %x) {
; CHECK-LABEL: @not_signbit_zext(
; CHECK-NEXT: [[A:%.*]] = xor i16 [[X:%.*]], -1
; CHECK-NEXT: [[R:%.*]] = lshr i16 [[A]], 15
; CHECK-NEXT: [[R2:%.*]] = zext i16 [[R]] to i32
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1
; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i32
; CHECK-NEXT: ret i32 [[R2]]
;
%a = xor i16 %x, -1
Expand All @@ -1017,9 +1016,8 @@ define i32 @not_signbit_zext(i16 %x) {

define i8 @not_signbit_trunc(i16 %x) {
; CHECK-LABEL: @not_signbit_trunc(
; CHECK-NEXT: [[A:%.*]] = xor i16 [[X:%.*]], -1
; CHECK-NEXT: [[R:%.*]] = lshr i16 [[A]], 15
; CHECK-NEXT: [[R2:%.*]] = trunc i16 [[R]] to i8
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1
; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i8
; CHECK-NEXT: ret i8 [[R2]]
;
%a = xor i16 %x, -1
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/Transforms/InstCombine/negated-bitmask.ll
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,8 @@ define i8 @neg_signbit_use2(i5 %x) {

define i32 @neg_not_signbit1(i8 %x) {
; CHECK-LABEL: @neg_not_signbit1(
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], -1
; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], 7
; CHECK-NEXT: [[R:%.*]] = zext i8 [[TMP2]] to i32
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i32
; CHECK-NEXT: ret i32 [[R]]
;
%s = lshr i8 %x, 7
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/xor.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1061,8 +1061,8 @@ define i8 @not_lshr(i8 %x) {

define <2 x i8> @not_lshr_vec(<2 x i8> %x) {
; CHECK-LABEL: @not_lshr_vec(
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
; CHECK-NEXT: [[R:%.*]] = lshr <2 x i8> [[TMP1]], <i8 7, i8 7>
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i8>
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%a = lshr <2 x i8> %x, <i8 7, i8 7>
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Transforms/InstCombine/zext.ll
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,10 @@ define i8 @notneg_zext_narrower_use(i32 %x) {

define i8 @disguised_signbit_clear_test(i64 %x) {
; CHECK-LABEL: @disguised_signbit_clear_test(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[TMP1]], -1
; CHECK-NEXT: [[TMP3:%.*]] = lshr i8 [[TMP2]], 7
; CHECK-NEXT: ret i8 [[TMP3]]
; CHECK-NEXT: [[A1:%.*]] = and i64 [[X:%.*]], 128
; CHECK-NEXT: [[T4:%.*]] = icmp eq i64 [[A1]], 0
; CHECK-NEXT: [[T6:%.*]] = zext i1 [[T4]] to i8
; CHECK-NEXT: ret i8 [[T6]]
;
%a1 = and i64 %x, 128
%t4 = icmp eq i64 %a1, 0
Expand Down

0 comments on commit 21d3871

Please sign in to comment.