Skip to content

[CVP][SCCP] Add support for uitofp nneg #86154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 43 additions & 7 deletions llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ STATISTIC(NumAShrsConverted, "Number of ashr converted to lshr");
STATISTIC(NumAShrsRemoved, "Number of ashr removed");
STATISTIC(NumSRems, "Number of srem converted to urem");
STATISTIC(NumSExt, "Number of sext converted to zext");
STATISTIC(NumSIToFP, "Number of sitofp converted to uitofp");
STATISTIC(NumSICmps, "Number of signed icmp preds simplified to unsigned");
STATISTIC(NumAnd, "Number of ands removed");
STATISTIC(NumNW, "Number of no-wrap deductions");
Expand Down Expand Up @@ -89,7 +90,7 @@ STATISTIC(NumSMinMax,
"Number of llvm.s{min,max} intrinsics simplified to unsigned");
STATISTIC(NumUDivURemsNarrowedExpanded,
"Number of bound udiv's/urem's expanded");
STATISTIC(NumZExt, "Number of non-negative deductions");
STATISTIC(NumNNeg, "Number of zext/uitofp non-negative deductions");

static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
if (Constant *C = LVI->getConstant(V, At))
Expand Down Expand Up @@ -1075,20 +1076,49 @@ static bool processSExt(SExtInst *SDI, LazyValueInfo *LVI) {
return true;
}

static bool processZExt(ZExtInst *ZExt, LazyValueInfo *LVI) {
if (ZExt->getType()->isVectorTy())
static bool processPossibleNonNeg(PossiblyNonNegInst *I, LazyValueInfo *LVI) {
if (I->getType()->isVectorTy())
return false;

if (ZExt->hasNonNeg())
if (I->hasNonNeg())
return false;

const Use &Base = ZExt->getOperandUse(0);
const Use &Base = I->getOperandUse(0);
if (!LVI->getConstantRangeAtUse(Base, /*UndefAllowed*/ false)
.isAllNonNegative())
return false;

++NumZExt;
ZExt->setNonNeg();
++NumNNeg;
I->setNonNeg();

return true;
}

static bool processZExt(ZExtInst *ZExt, LazyValueInfo *LVI) {
return processPossibleNonNeg(cast<PossiblyNonNegInst>(ZExt), LVI);
}

static bool processUIToFP(UIToFPInst *UIToFP, LazyValueInfo *LVI) {
return processPossibleNonNeg(cast<PossiblyNonNegInst>(UIToFP), LVI);
}

static bool processSIToFP(SIToFPInst *SIToFP, LazyValueInfo *LVI) {
if (SIToFP->getType()->isVectorTy())
return false;

const Use &Base = SIToFP->getOperandUse(0);
if (!LVI->getConstantRangeAtUse(Base, /*UndefAllowed*/ false)
.isAllNonNegative())
return false;

++NumSIToFP;
auto *UIToFP = CastInst::Create(Instruction::UIToFP, Base, SIToFP->getType(),
"", SIToFP->getIterator());
UIToFP->takeName(SIToFP);
UIToFP->setDebugLoc(SIToFP->getDebugLoc());
UIToFP->setNonNeg();
SIToFP->replaceAllUsesWith(UIToFP);
SIToFP->eraseFromParent();

return true;
}
Expand Down Expand Up @@ -1197,6 +1227,12 @@ static bool runImpl(Function &F, LazyValueInfo *LVI, DominatorTree *DT,
case Instruction::ZExt:
BBChanged |= processZExt(cast<ZExtInst>(&II), LVI);
break;
case Instruction::UIToFP:
BBChanged |= processUIToFP(cast<UIToFPInst>(&II), LVI);
break;
case Instruction::SIToFP:
BBChanged |= processSIToFP(cast<SIToFPInst>(&II), LVI);
break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
Expand Down
12 changes: 7 additions & 5 deletions llvm/lib/Transforms/Utils/SCCPSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ static bool refineInstruction(SCCPSolver &Solver,
Changed = true;
}
}
} else if (isa<ZExtInst>(Inst) && !Inst.hasNonNeg()) {
} else if (isa<PossiblyNonNegInst>(Inst) && !Inst.hasNonNeg()) {
auto Range = GetRange(Inst.getOperand(0));
if (Range.isAllNonNegative()) {
Inst.setNonNeg();
Expand Down Expand Up @@ -191,14 +191,16 @@ static bool replaceSignedInst(SCCPSolver &Solver,

Instruction *NewInst = nullptr;
switch (Inst.getOpcode()) {
// Note: We do not fold sitofp -> uitofp here because that could be more
// expensive in codegen and may not be reversible in the backend.
case Instruction::SIToFP:
case Instruction::SExt: {
// If the source value is not negative, this is a zext.
// If the source value is not negative, this is a zext/uitofp.
Value *Op0 = Inst.getOperand(0);
if (InsertedValues.count(Op0) || !isNonNegative(Op0))
return false;
NewInst = new ZExtInst(Op0, Inst.getType(), "", Inst.getIterator());
NewInst = CastInst::Create(Inst.getOpcode() == Instruction::SExt
? Instruction::ZExt
: Instruction::UIToFP,
Op0, Inst.getType(), "", Inst.getIterator());
NewInst->setNonNeg();
break;
}
Expand Down
99 changes: 99 additions & 0 deletions llvm/test/Transforms/CorrelatedValuePropagation/sitofp.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s

declare void @use.f32(float)

define void @test1(i32 %n) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1
; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
; CHECK: bb:
; CHECK-NEXT: [[EXT_WIDE:%.*]] = uitofp nneg i32 [[N]] to float
; CHECK-NEXT: call void @use.f32(float [[EXT_WIDE]])
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%cmp = icmp sgt i32 %n, -1
br i1 %cmp, label %bb, label %exit

bb:
%ext.wide = sitofp i32 %n to float
call void @use.f32(float %ext.wide)
br label %exit

exit:
ret void
}


define void @test2_fail(i32 %n) {
; CHECK-LABEL: @test2_fail(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -2
; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
; CHECK: bb:
; CHECK-NEXT: [[EXT_WIDE:%.*]] = sitofp i32 [[N]] to float
; CHECK-NEXT: call void @use.f32(float [[EXT_WIDE]])
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%cmp = icmp sgt i32 %n, -2
br i1 %cmp, label %bb, label %exit

bb:
%ext.wide = sitofp i32 %n to float
call void @use.f32(float %ext.wide)
br label %exit

exit:
ret void
}

define float @may_including_undef(i1 %c.1, i1 %c.2) {
; CHECK-LABEL: @may_including_undef(
; CHECK-NEXT: br i1 [[C_1:%.*]], label [[TRUE_1:%.*]], label [[FALSE:%.*]]
; CHECK: true.1:
; CHECK-NEXT: br i1 [[C_2:%.*]], label [[TRUE_2:%.*]], label [[EXIT:%.*]]
; CHECK: true.2:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: false:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[TRUE_1]] ], [ 1, [[TRUE_2]] ], [ undef, [[FALSE]] ]
; CHECK-NEXT: [[EXT:%.*]] = sitofp i32 [[P]] to float
; CHECK-NEXT: ret float [[EXT]]
;
br i1 %c.1, label %true.1, label %false

true.1:
br i1 %c.2, label %true.2, label %exit

true.2:
br label %exit

false:
br label %exit

exit:
%p = phi i32 [ 0, %true.1 ], [ 1, %true.2], [ undef, %false ]
%ext = sitofp i32 %p to float
ret float %ext
}

define double @test_infer_at_use(i32 noundef %n) {
; CHECK-LABEL: @test_infer_at_use(
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1
; CHECK-NEXT: [[EXT:%.*]] = uitofp nneg i32 [[N]] to double
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], double [[EXT]], double 0.000000e+00
; CHECK-NEXT: ret double [[SELECT]]
;
%cmp = icmp sgt i32 %n, -1
%ext = sitofp i32 %n to double
%select = select i1 %cmp, double %ext, double 0.0
ret double %select
}
98 changes: 98 additions & 0 deletions llvm/test/Transforms/CorrelatedValuePropagation/uitofp.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s

declare void @use.f32(float)

define void @test1(i32 %n) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1
; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
; CHECK: bb:
; CHECK-NEXT: [[EXT_WIDE:%.*]] = uitofp nneg i32 [[N]] to float
; CHECK-NEXT: call void @use.f32(float [[EXT_WIDE]])
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%cmp = icmp sgt i32 %n, -1
br i1 %cmp, label %bb, label %exit

bb:
%ext.wide = uitofp i32 %n to float
call void @use.f32(float %ext.wide)
br label %exit

exit:
ret void
}

define void @test2_fail(i32 %n) {
; CHECK-LABEL: @test2_fail(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -2
; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
; CHECK: bb:
; CHECK-NEXT: [[EXT_WIDE:%.*]] = uitofp i32 [[N]] to float
; CHECK-NEXT: call void @use.f32(float [[EXT_WIDE]])
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%cmp = icmp sgt i32 %n, -2
br i1 %cmp, label %bb, label %exit

bb:
%ext.wide = uitofp i32 %n to float
call void @use.f32(float %ext.wide)
br label %exit

exit:
ret void
}

define float @may_including_undef(i1 %c.1, i1 %c.2) {
; CHECK-LABEL: @may_including_undef(
; CHECK-NEXT: br i1 [[C_1:%.*]], label [[TRUE_1:%.*]], label [[FALSE:%.*]]
; CHECK: true.1:
; CHECK-NEXT: br i1 [[C_2:%.*]], label [[TRUE_2:%.*]], label [[EXIT:%.*]]
; CHECK: true.2:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: false:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[TRUE_1]] ], [ 1, [[TRUE_2]] ], [ undef, [[FALSE]] ]
; CHECK-NEXT: [[EXT:%.*]] = uitofp i32 [[P]] to float
; CHECK-NEXT: ret float [[EXT]]
;
br i1 %c.1, label %true.1, label %false

true.1:
br i1 %c.2, label %true.2, label %exit

true.2:
br label %exit

false:
br label %exit

exit:
%p = phi i32 [ 0, %true.1 ], [ 1, %true.2], [ undef, %false ]
%ext = uitofp i32 %p to float
ret float %ext
}

define double @test_infer_at_use(i32 noundef %n) {
; CHECK-LABEL: @test_infer_at_use(
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], -1
; CHECK-NEXT: [[EXT:%.*]] = uitofp nneg i32 [[N]] to double
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], double [[EXT]], double 0.000000e+00
; CHECK-NEXT: ret double [[SELECT]]
;
%cmp = icmp sgt i32 %n, -1
%ext = uitofp i32 %n to double
%select = select i1 %cmp, double %ext, double 0.0
ret double %select
}
6 changes: 3 additions & 3 deletions llvm/test/Transforms/SCCP/ip-ranges-casts.ll
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ define i1 @caller.sext() {
define internal i1 @f.fptosi(i32 %x) {
; CHECK-LABEL: define internal i1 @f.fptosi(
; CHECK-SAME: i32 [[X:%.*]]) {
; CHECK-NEXT: [[TO_DOUBLE:%.*]] = sitofp i32 [[X]] to double
; CHECK-NEXT: [[TO_DOUBLE:%.*]] = uitofp nneg i32 [[X]] to double
; CHECK-NEXT: [[ADD:%.*]] = fadd double 0.000000e+00, [[TO_DOUBLE]]
; CHECK-NEXT: [[TO_I32:%.*]] = fptosi double [[ADD]] to i32
; CHECK-NEXT: [[C_1:%.*]] = icmp sgt i32 [[TO_I32]], 300
Expand Down Expand Up @@ -209,7 +209,7 @@ define i1 @caller.fptosi() {
define internal i1 @f.fpext(i16 %x) {
; CHECK-LABEL: define internal i1 @f.fpext(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TO_FLOAT:%.*]] = sitofp i16 [[X]] to float
; CHECK-NEXT: [[TO_FLOAT:%.*]] = uitofp nneg i16 [[X]] to float
; CHECK-NEXT: [[TO_DOUBLE:%.*]] = fpext float [[TO_FLOAT]] to double
; CHECK-NEXT: [[TO_I64:%.*]] = fptoui float [[TO_FLOAT]] to i64
; CHECK-NEXT: [[C_1:%.*]] = icmp sgt i64 [[TO_I64]], 300
Expand Down Expand Up @@ -293,7 +293,7 @@ define i1 @int_range_to_double_cast(i32 %a) {
; CHECK-LABEL: define i1 @int_range_to_double_cast(
; CHECK-SAME: i32 [[A:%.*]]) {
; CHECK-NEXT: [[R:%.*]] = and i32 [[A]], 255
; CHECK-NEXT: [[T4:%.*]] = sitofp i32 [[R]] to double
; CHECK-NEXT: [[T4:%.*]] = uitofp nneg i32 [[R]] to double
; CHECK-NEXT: [[T10:%.*]] = fadd double 0.000000e+00, [[T4]]
; CHECK-NEXT: [[T11:%.*]] = fcmp olt double [[T4]], [[T10]]
; CHECK-NEXT: ret i1 [[T11]]
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Transforms/SCCP/sitofp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
define float @sitofp_and(i8 %x) {
; CHECK-LABEL: @sitofp_and(
; CHECK-NEXT: [[PX:%.*]] = and i8 [[X:%.*]], 127
; CHECK-NEXT: [[R:%.*]] = sitofp i8 [[PX]] to float
; CHECK-NEXT: [[R:%.*]] = uitofp nneg i8 [[PX]] to float
; CHECK-NEXT: ret float [[R]]
;
%px = and i8 %x, 127
Expand All @@ -23,7 +23,7 @@ define half @sitofp_const(i8 %x) {
define double @sitofp_zext(i7 %x) {
; CHECK-LABEL: @sitofp_zext(
; CHECK-NEXT: [[PX:%.*]] = zext i7 [[X:%.*]] to i8
; CHECK-NEXT: [[R:%.*]] = sitofp i8 [[PX]] to double
; CHECK-NEXT: [[R:%.*]] = uitofp nneg i8 [[PX]] to double
; CHECK-NEXT: ret double [[R]]
;
%px = zext i7 %x to i8
Expand Down Expand Up @@ -52,7 +52,7 @@ define float @dominating_condition(i32 %x) {
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
; CHECK: t:
; CHECK-NEXT: [[A:%.*]] = sitofp i32 [[X]] to float
; CHECK-NEXT: [[A:%.*]] = uitofp nneg i32 [[X]] to float
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: f:
; CHECK-NEXT: br label [[EXIT]]
Expand Down Expand Up @@ -86,7 +86,7 @@ define float @dominating_condition_alt(i32 %x) {
; CHECK: t:
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: f:
; CHECK-NEXT: [[A:%.*]] = sitofp i32 [[X]] to float
; CHECK-NEXT: [[A:%.*]] = uitofp nneg i32 [[X]] to float
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[COND:%.*]] = phi float [ -4.200000e+01, [[T]] ], [ [[A]], [[F]] ]
Expand Down