Skip to content
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
}