Skip to content

Commit

Permalink
[CVP] Eliminate urem when LHS < RHS
Browse files Browse the repository at this point in the history
Fol `X % Y -> X` when we can determine `X < Y` based on constant
range information.

Fixes #58408.

Differential Revision: https://reviews.llvm.org/D138360
  • Loading branch information
caojoshua authored and nikic committed Dec 13, 2022
1 parent 4f3b1c6 commit cca01df
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
32 changes: 29 additions & 3 deletions llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Expand Up @@ -768,13 +768,27 @@ static bool narrowSDivOrSRem(BinaryOperator *Instr, LazyValueInfo *LVI) {
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.
Expand Down Expand Up @@ -812,6 +826,18 @@ static bool processUDivOrURem(BinaryOperator *Instr, LazyValueInfo *LVI) {
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())
Expand Down
20 changes: 20 additions & 0 deletions llvm/test/Transforms/CorrelatedValuePropagation/urem.ll
Expand Up @@ -152,6 +152,26 @@ exit:
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
Expand Down

0 comments on commit cca01df

Please sign in to comment.