Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -1150,6 +1150,18 @@ if (Value *V = simplifyDivRem(Opcode, Op0, Op1, Q, MaxRecurse)) return V; + // If this is an exact divide by a constant, then the dividend (Op0) must have + // at least as many trailing zeros as the divisor to divide evenly. If it has + // less trailing zeros, then the result must be poison. + const APInt *DivC; + auto *PEO = dyn_cast_if_present(Q.CxtI); + if (PEO && PEO->isExact() && match(Op1, m_APInt(DivC)) && + DivC->countTrailingZeros()) { + KnownBits KnownOp0 = computeKnownBits(Op0, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); + if (KnownOp0.countMaxTrailingZeros() < DivC->countTrailingZeros()) + return PoisonValue::get(Op0->getType()); + } + bool IsSigned = Opcode == Instruction::SDiv; // (X rem Y) / Y -> 0 Index: llvm/test/Transforms/InstCombine/udiv-simplify.ll =================================================================== --- llvm/test/Transforms/InstCombine/udiv-simplify.ll +++ llvm/test/Transforms/InstCombine/udiv-simplify.ll @@ -95,13 +95,11 @@ ret i8 %u } -; TODO: This can't divide evenly, so it is poison. +; This can't divide evenly, so it is poison. define i8 @udiv_exact_demanded_low_bits_set(i8 %a) { ; CHECK-LABEL: @udiv_exact_demanded_low_bits_set( -; CHECK-NEXT: [[O:%.*]] = or i8 [[A:%.*]], 3 -; CHECK-NEXT: [[U:%.*]] = udiv exact i8 [[O]], 12 -; CHECK-NEXT: ret i8 [[U]] +; CHECK-NEXT: ret i8 poison ; %o = or i8 %a, 3 %u = udiv exact i8 %o, 12 Index: llvm/test/Transforms/InstSimplify/div.ll =================================================================== --- llvm/test/Transforms/InstSimplify/div.ll +++ llvm/test/Transforms/InstSimplify/div.ll @@ -333,17 +333,19 @@ ret i1 %rem } +; Can't divide evenly, so create poison. + define i8 @sdiv_exact_trailing_zeros(i8 %x) { ; CHECK-LABEL: @sdiv_exact_trailing_zeros( -; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1 -; CHECK-NEXT: [[R:%.*]] = sdiv exact i8 [[O]], -42 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 poison ; %o = or i8 %x, 1 ; odd number %r = sdiv exact i8 %o, -42 ; can't divide exactly ret i8 %r } +; Negative test - could divide evenly. + define i8 @sdiv_exact_trailing_zeros_eq(i8 %x) { ; CHECK-LABEL: @sdiv_exact_trailing_zeros_eq( ; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 2 @@ -355,6 +357,8 @@ ret i8 %r } +; Negative test - must be exact div. + define i8 @sdiv_trailing_zeros(i8 %x) { ; CHECK-LABEL: @sdiv_trailing_zeros( ; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1 @@ -366,17 +370,19 @@ ret i8 %r } +; Can't divide evenly, so create poison. + define <2 x i8> @udiv_exact_trailing_zeros(<2 x i8> %x) { ; CHECK-LABEL: @udiv_exact_trailing_zeros( -; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = udiv exact <2 x i8> [[O]], -; CHECK-NEXT: ret <2 x i8> [[R]] +; CHECK-NEXT: ret <2 x i8> poison ; %o = or <2 x i8> %x, %r = udiv exact <2 x i8> %o, ; can't divide exactly ret <2 x i8> %r } +; Negative test - could divide evenly. + define <2 x i8> @udiv_exact_trailing_zeros_eq(<2 x i8> %x) { ; CHECK-LABEL: @udiv_exact_trailing_zeros_eq( ; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], @@ -388,6 +394,8 @@ ret <2 x i8> %r } +; Negative test - must be exact div. + define i8 @udiv_trailing_zeros(i8 %x) { ; CHECK-LABEL: @udiv_trailing_zeros( ; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1