diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 5545ec3b3ed0c..e8458ed9090f5 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -5069,6 +5069,9 @@ MachineInstr *CombinerHelper::buildUDivUsingMul(MachineInstr &MI) { const unsigned EltBits = ScalarTy.getScalarSizeInBits(); LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(Ty); LLT ScalarShiftAmtTy = ShiftAmtTy.getScalarType(); + + unsigned KnownLeadingZeros = + KB ? KB->getKnownBits(LHS).countMinLeadingZeros() : 0; auto &MIB = Builder; bool UseNPQ = false; @@ -5086,8 +5089,12 @@ MachineInstr *CombinerHelper::buildUDivUsingMul(MachineInstr &MI) { // at the end. // TODO: Use undef values for divisor of 1. if (!Divisor.isOne()) { + + // UnsignedDivisionByConstantInfo doesn't work correctly if leading zeros + // in the dividend exceeds the leading zeros for the divisor. UnsignedDivisionByConstantInfo magics = - UnsignedDivisionByConstantInfo::get(Divisor); + UnsignedDivisionByConstantInfo::get( + Divisor, std::min(KnownLeadingZeros, Divisor.countl_zero())); Magic = std::move(magics.Magic); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll index 9a525151ca328..c97a00ccdd455 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll @@ -243,3 +243,29 @@ define <8 x i16> @pr38477(<8 x i16> %a0) { %1 = udiv <8 x i16> %a0, ret <8 x i16> %1 } + +define i32 @udiv_div_by_180(i32 %x) +; SDAG-LABEL: udiv_div_by_180: +; SDAG: // %bb.0: +; SDAG-NEXT: mov w8, #5826 // =0x16c2 +; SDAG-NEXT: and w9, w0, #0xff +; SDAG-NEXT: movk w8, #364, lsl #16 +; SDAG-NEXT: umull x8, w9, w8 +; SDAG-NEXT: lsr x0, x8, #32 +; SDAG-NEXT: // kill: def $w0 killed $w0 killed $x0 +; SDAG-NEXT: ret +; +; GISEL-LABEL: udiv_div_by_180: +; GISEL: // %bb.0: +; GISEL-NEXT: uxtb w8, w0 +; GISEL-NEXT: mov w9, #5826 // =0x16c2 +; GISEL-NEXT: movk w9, #364, lsl #16 +; GISEL-NEXT: umull x8, w8, w9 +; GISEL-NEXT: lsr x0, x8, #32 +; GISEL-NEXT: // kill: def $w0 killed $w0 killed $x0 +; GISEL-NEXT: ret +{ + %truncate = and i32 %x, 255 + %udiv = udiv i32 %truncate, 180 + ret i32 %udiv +}