diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp index 6694d5cc06c8c..62b7830116de1 100644 --- a/llvm/lib/Analysis/DemandedBits.cpp +++ b/llvm/lib/Analysis/DemandedBits.cpp @@ -246,6 +246,31 @@ void DemandedBits::determineLiveOperandBits( else AB &= ~(Known.One & ~Known2.One); break; + case Instruction::SRem: + case Instruction::URem: + case Instruction::UDiv: + case Instruction::SDiv: { + auto Opc = UserI->getOpcode(); + auto IsDiv = Opc == Instruction::UDiv || Opc == Instruction::SDiv; + bool IsSigned = Opc == Instruction::SDiv || Opc == Instruction::SRem; + if (OperandNo == 0) { + const APInt *DivAmnt; + if (match(UserI->getOperand(1), m_APInt(DivAmnt))) { + if (DivAmnt->isPowerOf2()) { + unsigned Sh = DivAmnt->countr_zero(); + if (IsDiv) { + AB = AOut.shl(Sh); + } else { + AB = AOut & APInt::getLowBitsSet(BitWidth, Sh); + } + if (IsSigned) { + AB.setSignBit(); + } + } + } + } + break; + } case Instruction::Xor: case Instruction::PHI: AB = AOut; diff --git a/llvm/test/Analysis/DemandedBits/div_rem.ll b/llvm/test/Analysis/DemandedBits/div_rem.ll new file mode 100644 index 0000000000000..1f8c958f20380 --- /dev/null +++ b/llvm/test/Analysis/DemandedBits/div_rem.ll @@ -0,0 +1,282 @@ +; RUN: opt -S -disable-output -passes="print" < %s 2>&1 | FileCheck %s + +define i8 @test_sdiv_const_amount_4(i32 %a) { +; CHECK-LABEL: 'test_sdiv_const_amount_4' +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div = sdiv i32 %a, 4 +; CHECK-DAG: DemandedBits: 0x3fc for %a in %div = sdiv i32 %a, 4 +; CHECK-DAG: DemandedBits: 0xffffffff for 4 in %div = sdiv i32 %a, 4 +; + %div = sdiv i32 %a, 4 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_sdiv_const_amount_5(i32 %a) { +; CHECK-LABEL: 'test_sdiv_const_amount_5' +; CHECK-DAG: DemandedBits: 0xff for %div = sdiv i32 %a, 5 +; CHECK-DAG: DemandedBits: 0xfff for %a in %div = sdiv i32 %a, 5 +; CHECK-DAG: DemandedBits: 0xffffffff for 5 in %div = sdiv i32 %a, 5 +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; + %div = sdiv i32 %a, 5 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_sdiv_const_amount_8(i32 %a) { +; CHECK-LABEL: 'test_sdiv_const_amount_8' +; CHECK-DAG: DemandedBits: 0xff for %div = sdiv i32 %a, 8 +; CHECK-DAG: DemandedBits: 0x7f8 for %a in %div = sdiv i32 %a, 8 +; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %div = sdiv i32 %a, 8 +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; + %div = sdiv i32 %a, 8 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_sdiv_const_amount_9(i32 %a) { +; CHECK-LABEL: 'test_sdiv_const_amount_9' +; CHECK-DAG: DemandedBits: 0xff for %div = udiv i32 %a, 9 +; CHECK-DAG: DemandedBits: 0xfff for %a in %div = udiv i32 %a, 9 +; CHECK-DAG: DemandedBits: 0xffffffff for 9 in %div = udiv i32 %a, 9 +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; + %div = udiv i32 %a, 9 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_sdiv(i32 %a, i32 %b) { +; CHECK-LABEL: 'test_sdiv' +; CHECK-DAG: DemandedBits: 0xff for %div = sdiv i32 %a, %b +; CHECK-DAG: DemandedBits: 0xffffffff for %a in %div = sdiv i32 %a, %b +; CHECK-DAG: DemandedBits: 0xffffffff for %b in %div = sdiv i32 %a, %b +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; + %div = sdiv i32 %a, %b + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_udiv_const_amount_4(i32 %a) { +; CHECK-LABEL: 'test_udiv_const_amount_4' +; CHECK-DAG: DemandedBits: 0xff for %div = udiv i32 %a, 4 +; CHECK-DAG: DemandedBits: 0x3fc for %a in %div = udiv i32 %a, 4 +; CHECK-DAG: DemandedBits: 0xffffffff for 4 in %div = udiv i32 %a, 4 +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; + %div = udiv i32 %a, 4 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_udiv_const_amount_5(i32 %a) { +; CHECK-LABEL: 'test_udiv_const_amount_5' +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div = udiv i32 %a, 5 +; CHECK-DAG: DemandedBits: 0x7ff for %a in %div = udiv i32 %a, 5 +; CHECK-DAG: DemandedBits: 0xffffffff for 5 in %div = udiv i32 %a, 5 +; + %div = udiv i32 %a, 5 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_udiv_const_amount_8(i32 %a) { +; CHECK-LABEL: 'test_udiv_const_amount_8' +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div = udiv i32 %a, 8 +; CHECK-DAG: DemandedBits: 0x7f8 for %a in %div = udiv i32 %a, 8 +; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %div = udiv i32 %a, 8 +; + %div = udiv i32 %a, 8 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_udiv_const_amount_9(i32 %a) { +; CHECK-LABEL: 'test_udiv_const_amount_9' +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div = udiv i32 %a, 9 +; CHECK-DAG: DemandedBits: 0xfff for %a in %div = udiv i32 %a, 9 +; CHECK-DAG: DemandedBits: 0xffffffff for 9 in %div = udiv i32 %a, 9 +; + %div = udiv i32 %a, 9 + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_udiv(i32 %a, i32 %b) { +; CHECK-LABEL: 'test_udiv' +; CHECK-DAG: DemandedBits: 0xff for %div = udiv i32 %a, %b +; CHECK-DAG: DemandedBits: 0xffffffff for %a in %div = udiv i32 %a, %b +; CHECK-DAG: DemandedBits: 0xffffffff for %b in %div = udiv i32 %a, %b +; CHECK-DAG: DemandedBits: 0xff for %div.t = trunc i32 %div to i8 +; CHECK-DAG: DemandedBits: 0xff for %div in %div.t = trunc i32 %div to i8 +; + %div = udiv i32 %a, %b + %div.t = trunc i32 %div to i8 + ret i8 %div.t +} + +define i8 @test_srem_zext_trunc_const_amount2(i8 %a) { +; CHECK-LABEL: 'test_srem_zext_trunc_const_amount2' +; 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 %ext, 2 +; CHECK-DAG: DemandedBits: 0x80000001 for %ext in %rem = srem i32 %ext, 2 +; CHECK-DAG: DemandedBits: 0xffffffff for 2 in %rem = srem i32 %ext, 2 +; 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: 0xffffffff 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.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, 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 +; + %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.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, 8 +; CHECK-DAG: DemandedBits: 0x80000007 for %a in %rem = srem i32 %a, 8 +; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %rem = srem i32 %a, 8 +; + %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 = srem i32 %a, %b +; CHECK-DAG: DemandedBits: 0xff for %rem in %rem.t = trunc i32 %rem to i8 +; 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 +} + +define i8 @test_urem_const_amount_4(i32 %a) { +; CHECK-LABEL: 'test_urem_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 = urem i32 %a, 4 +; CHECK-DAG: DemandedBits: 0x3 for %a in %rem = urem i32 %a, 4 +; CHECK-DAG: DemandedBits: 0xffffffff for 4 in %rem = urem i32 %a, 4 +; + %rem = urem i32 %a, 4 + %rem.t = trunc i32 %rem to i8 + ret i8 %rem.t +} + + + + + + +define i8 @test_urem_const_amount_5(i32 %a) { +; CHECK-LABEL: 'test_urem_const_amount_5' +; CHECK-DAG: DemandedBits: 0xff for %rem = urem i32 %a, 5 +; CHECK-DAG: DemandedBits: 0xffffffff for %a in %rem = urem i32 %a, 5 +; CHECK-DAG: DemandedBits: 0xffffffff for 5 in %rem = urem 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 = urem i32 %a, 5 + %rem.t = trunc i32 %rem to i8 + ret i8 %rem.t +} + +define i8 @test_urem_const_amount_8(i32 %a) { +; CHECK-LABEL: 'test_urem_const_amount_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 +; CHECK-DAG: DemandedBits: 0xff for %rem = urem i32 %a, 8 +; CHECK-DAG: DemandedBits: 0x7 for %a in %rem = urem i32 %a, 8 +; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %rem = urem i32 %a, 8 +; + %rem = urem i32 %a, 8 + %rem.t = trunc i32 %rem to i8 + ret i8 %rem.t +} + +define i8 @test_urem_const_amount_9(i32 %a) { +; CHECK-LABEL: 'test_urem_const_amount_9' +; CHECK-DAG: DemandedBits: 0xff for %rem = urem i32 %a, 9 +; CHECK-DAG: DemandedBits: 0xffffffff for %a in %rem = urem i32 %a, 9 +; CHECK-DAG: DemandedBits: 0xffffffff for 9 in %rem = urem i32 %a, 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 +; + %rem = urem i32 %a, 9 + %rem.t = trunc i32 %rem to i8 + ret i8 %rem.t +} + +define i8 @test_urem(i32 %a, i32 %b) { +; CHECK-LABEL: 'test_urem' +; CHECK-DAG: DemandedBits: 0xff for %rem = urem i32 %a, %b +; CHECK-DAG: DemandedBits: 0xffffffff for %a in %rem = urem i32 %a, %b +; CHECK-DAG: DemandedBits: 0xffffffff for %b in %rem = urem i32 %a, %b +; 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 = urem i32 %a, %b + %rem.t = trunc i32 %rem to i8 + ret i8 %rem.t +}