diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -768,13 +768,27 @@ return true; } +static bool processURem(BinaryOperator *Instr, LazyValueInfo *LVI) { + assert(Instr->getOpcode() == Instruction::URem); + assert(!Instr->getType()->isVectorTy()); + + // X % Y -> X for X < Y + if (LVI->getConstantRange(Instr->getOperand(0), Instr) + .icmp(ICmpInst::ICMP_ULT, + LVI->getConstantRange(Instr->getOperand(1), Instr))) { + Instr->replaceAllUsesWith(Instr->getOperand(0)); + Instr->eraseFromParent(); + return true; + } + return false; +} + /// Try to shrink a udiv/urem's width down to the smallest power of two that's /// sufficient to contain its operands. -static bool processUDivOrURem(BinaryOperator *Instr, LazyValueInfo *LVI) { +static bool narrowUDivOrURem(BinaryOperator *Instr, LazyValueInfo *LVI) { assert(Instr->getOpcode() == Instruction::UDiv || Instr->getOpcode() == Instruction::URem); - if (Instr->getType()->isVectorTy()) - return false; + assert(!Instr->getType()->isVectorTy()); // Find the smallest power of two bitwidth that's sufficient to hold Instr's // operands. @@ -812,6 +826,18 @@ return true; } +static bool processUDivOrURem(BinaryOperator *Instr, LazyValueInfo *LVI) { + assert(Instr->getOpcode() == Instruction::UDiv || + Instr->getOpcode() == Instruction::URem); + if (Instr->getType()->isVectorTy()) + return false; + + if (Instr->getOpcode() == Instruction::URem && processURem(Instr, LVI)) + return true; + + return narrowUDivOrURem(Instr, LVI); +} + static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) { assert(SDI->getOpcode() == Instruction::SRem); if (SDI->getType()->isVectorTy()) diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/urem.ll b/llvm/test/Transforms/CorrelatedValuePropagation/urem.ll --- a/llvm/test/Transforms/CorrelatedValuePropagation/urem.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/urem.ll @@ -152,6 +152,26 @@ ret void } +declare void @llvm.assume(i1) + +define i16 @test7(i16 %x, i16 %y) { +; CHECK-LABEL: @test7( +; CHECK-NEXT: [[ABOVE_RANGE:%.*]] = icmp uge i16 [[Y:%.*]], 13 +; CHECK-NEXT: call void @llvm.assume(i1 [[ABOVE_RANGE]]) +; CHECK-NEXT: [[BELOW_RANGE:%.*]] = icmp ult i16 [[X:%.*]], 13 +; CHECK-NEXT: call void @llvm.assume(i1 [[BELOW_RANGE]]) +; CHECK-NEXT: ret i16 [[X]] +; + %above_range = icmp uge i16 %y, 13 + call void @llvm.assume(i1 %above_range) + + %below_range = icmp ult i16 %x, 13 + call void @llvm.assume(i1 %below_range) + + %r = urem i16 %x, %y + ret i16 %r +} + define void @non_power_of_2(i24 %n) { ; CHECK-LABEL: @non_power_of_2( ; CHECK-NEXT: [[DIV:%.*]] = urem i24 [[N:%.*]], 42