Skip to content

[DemandedBits] Add div/rem support #148853

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
14 changes: 14 additions & 0 deletions llvm/lib/Analysis/DemandedBits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,20 @@ void DemandedBits::determineLiveOperandBits(
else
AB &= ~(Known.One & ~Known2.One);
break;
case Instruction::SRem: {
// urem and udiv will be converted to and/lshr
// multiple times and early on. So, we don't
// need to calculate demanded-bits for those.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment looks oddly narrow.

const APInt *DivAmnt;
if (match(UserI->getOperand(1), m_APInt(DivAmnt))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (match(UserI->getOperand(1), m_APInt(DivAmnt))) {
if (match(UserI->getOperand(1), m_Power2(DivAmnt))) {

Then you don't need the separate check.

if (DivAmnt->isPowerOf2()) {
unsigned Sh = DivAmnt->countr_zero();
AB = AOut & APInt::getLowBitsSet(BitWidth, Sh);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
AB = AOut & APInt::getLowBitsSet(BitWidth, Sh);
AB = AOut & (DivAmnt - 1);

A slightly simpler way to express this (matching InstCombineSimplifyDemanded).

AB.setSignBit();
}
}
break;
}
case Instruction::Xor:
case Instruction::PHI:
AB = AOut;
Expand Down
83 changes: 83 additions & 0 deletions llvm/test/Analysis/DemandedBits/rem.ll
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think none of the tests currently show the influence of the AOut demanded bits on AB. If you're using trunc i8, you need to test a pow2 >= 512 for that.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s


define i8 @test_srem_zext_trunc_const_amount2(i8 %a) {
; CHECK-LABEL: 'test_srem_zext_trunc_const_amount2'
; CHECK-DAG: DemandedBits: 0xff for %rem = srem i32 %ext, 2
; CHECK-DAG: DemandedBits: 0x80000001 for %ext in %rem = srem i32 %ext, 2
; CHECK-DAG: DemandedBits: 0x80000001 for 2 in %rem = srem i32 %ext, 2
; CHECK-DAG: DemandedBits: 0xff for %rem in %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0x80000001 for %ext = sext i8 %a to i32
; CHECK-DAG: DemandedBits: 0x81 for %a in %ext = sext i8 %a to i32
;
%ext = sext i8 %a to i32
%rem = srem i32 %ext, 2
%rem.t = trunc i32 %rem to i8
ret i8 %rem.t
}

define i8 @test_srem_const_amount_4(i32 %a) {
; CHECK-LABEL: 'test_srem_const_amount_4'
; CHECK-DAG: DemandedBits: 0xff for %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem in %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem = srem i32 %a, 4
; CHECK-DAG: DemandedBits: 0x80000003 for %a in %rem = srem i32 %a, 4
; CHECK-DAG: DemandedBits: 0x80000003 for 4 in %rem = srem i32 %a, 4
;
%rem = srem i32 %a, 4
%rem.t = trunc i32 %rem to i8
ret i8 %rem.t
}

define i8 @test_srem_const_amount_5(i32 %a) {
; CHECK-LABEL: 'test_srem_const_amount_5'
; CHECK-DAG: DemandedBits: 0xff for %rem = srem i32 %a, 5
; CHECK-DAG: DemandedBits: 0xffffffff for %a in %rem = srem i32 %a, 5
; CHECK-DAG: DemandedBits: 0xffffffff for 5 in %rem = srem i32 %a, 5
; CHECK-DAG: DemandedBits: 0xff for %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem in %rem.t = trunc i32 %rem to i8
;
%rem = srem i32 %a, 5
%rem.t = trunc i32 %rem to i8
ret i8 %rem.t
}

define i8 @test_srem_const_amount_8(i32 %a) {
; CHECK-LABEL: 'test_srem_const_amount_8'
; CHECK-DAG: DemandedBits: 0xff for %rem = srem i32 %a, 8
; CHECK-DAG: DemandedBits: 0x80000007 for %a in %rem = srem i32 %a, 8
; CHECK-DAG: DemandedBits: 0x80000007 for 8 in %rem = srem i32 %a, 8
; CHECK-DAG: DemandedBits: 0xff for %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem in %rem.t = trunc i32 %rem to i8
;
%rem = srem i32 %a, 8
%rem.t = trunc i32 %rem to i8
ret i8 %rem.t
}

define i8 @test_srem_const_amount_9(i32 %a) {
; CHECK-LABEL: 'test_srem_const_amount_9'
; CHECK-DAG: DemandedBits: 0xff for %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem in %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem = srem i32 %a, 9
; CHECK-DAG: DemandedBits: 0xffffffff for %a in %rem = srem i32 %a, 9
; CHECK-DAG: DemandedBits: 0xffffffff for 9 in %rem = srem i32 %a, 9
;
%rem = srem i32 %a, 9
%rem.t = trunc i32 %rem to i8
ret i8 %rem.t
}

define i8 @test_srem(i32 %a, i32 %b) {
; CHECK-LABEL: 'test_srem'
; CHECK-DAG: DemandedBits: 0xff for %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem in %rem.t = trunc i32 %rem to i8
; CHECK-DAG: DemandedBits: 0xff for %rem = srem i32 %a, %b
; CHECK-DAG: DemandedBits: 0xffffffff for %a in %rem = srem i32 %a, %b
; CHECK-DAG: DemandedBits: 0xffffffff for %b in %rem = srem i32 %a, %b
;
%rem = srem i32 %a, %b
%rem.t = trunc i32 %rem to i8
ret i8 %rem.t
}