Skip to content
Merged
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
18 changes: 16 additions & 2 deletions llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,18 @@ static bool ConvertToSInt(const APFloat &APF, int64_t &IntVal) {
return true;
}

// Ensure we stay within the bounds of fp values that can be represented as
// integers without gaps, which are 2^24 and 2^53 for IEEE-754 single and double
// precision respectively (both on negative and positive side).
static bool isRepresentableAsExactInteger(ConstantFP *FPVal, int64_t IntVal) {
const auto &InitValueFltSema = FPVal->getValueAPF().getSemantics();
if (!APFloat::isIEEELikeFP(InitValueFltSema))
return false;

return isUIntN(APFloat::semanticsPrecision(InitValueFltSema),
AbsoluteValue(IntVal));
}

/// If the loop has floating induction variable then insert corresponding
/// integer induction variable if possible.
/// For example,
Expand All @@ -212,7 +224,8 @@ bool IndVarSimplify::handleFloatingPointIV(Loop *L, PHINode *PN) {
auto *InitValueVal = dyn_cast<ConstantFP>(PN->getIncomingValue(IncomingEdge));

int64_t InitValue;
if (!InitValueVal || !ConvertToSInt(InitValueVal->getValueAPF(), InitValue))
if (!InitValueVal || !ConvertToSInt(InitValueVal->getValueAPF(), InitValue) ||
!isRepresentableAsExactInteger(InitValueVal, InitValue))
return false;

// Check IV increment. Reject this PN if increment operation is not
Expand Down Expand Up @@ -262,7 +275,8 @@ bool IndVarSimplify::handleFloatingPointIV(Loop *L, PHINode *PN) {
ConstantFP *ExitValueVal = dyn_cast<ConstantFP>(Compare->getOperand(1));
int64_t ExitValue;
if (ExitValueVal == nullptr ||
!ConvertToSInt(ExitValueVal->getValueAPF(), ExitValue))
!ConvertToSInt(ExitValueVal->getValueAPF(), ExitValue) ||
!isRepresentableAsExactInteger(ExitValueVal, ExitValue))
return false;

// Find new predicate for integer comparison.
Expand Down
137 changes: 137 additions & 0 deletions llvm/test/Transforms/IndVarSimplify/floating-point-iv.ll
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,140 @@ loop:
exit:
ret void
}

define void @test_fp_to_int_irrealizable_initval() {
; CHECK-LABEL: @test_fp_to_int_irrealizable_initval(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi float [ 1.000000e+08, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @opaque()
; CHECK-NEXT: [[IV_NEXT]] = fadd float [[IV]], -1.700000e+01
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult float [[IV_NEXT]], 2.500000e+01
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop

loop:
%iv = phi float [ 1.000000e+08, %entry ], [ %iv.next, %loop ]
call void @opaque()
%iv.next = fadd float %iv, -1.700000e+01
%cmp = fcmp ult float %iv.next, 2.500000e+01
br i1 %cmp, label %exit, label %loop

exit:
ret void
}

define void @test_fp_to_int_irrealizable_exitval() {
; CHECK-LABEL: @test_fp_to_int_irrealizable_exitval(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi float [ 2.500000e+01, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @opaque()
; CHECK-NEXT: [[IV_NEXT]] = fadd float [[IV]], 1.700000e+01
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[IV_NEXT]], 1.000000e+08
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop

loop:
%iv = phi float [ 2.500000e+01, %entry ], [ %iv.next, %loop ]
call void @opaque()
%iv.next = fadd float %iv, 1.700000e+01
%cmp = fcmp ugt float %iv.next, 1.000000e+08
br i1 %cmp, label %exit, label %loop

exit:
ret void
}

define void @test_fp_to_int_irrealizable_negative_exitval() {
; CHECK-LABEL: @test_fp_to_int_irrealizable_negative_exitval(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi float [ -2.500000e+01, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @opaque()
; CHECK-NEXT: [[IV_NEXT]] = fadd float [[IV]], -1.700000e+01
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult float [[IV_NEXT]], -1.000000e+08
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop

loop:
%iv = phi float [ -2.500000e+01, %entry ], [ %iv.next, %loop ]
call void @opaque()
%iv.next = fadd float %iv, -1.700000e+01
%cmp = fcmp ult float %iv.next, -1.000000e+08
br i1 %cmp, label %exit, label %loop

exit:
ret void
}

define void @test_fp_to_int_irrealizable_exitval_pow_2_24() {
; CHECK-LABEL: @test_fp_to_int_irrealizable_exitval_pow_2_24(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @opaque()
; CHECK-NEXT: [[IV_NEXT]] = fadd float [[IV]], 1.000000e+00
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[IV_NEXT]], 0x4170000000000000
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop

loop:
%iv = phi float [ 0.000000e+00, %entry ], [ %iv.next, %loop ]
call void @opaque()
%iv.next = fadd float %iv, 1.000000e+00
%cmp = fcmp ugt float %iv.next, 0x4170000000000000
br i1 %cmp, label %exit, label %loop

exit:
ret void
}

define void @test_fp_to_int_irrealizable_exitval_int64_min() {
; CHECK-LABEL: @test_fp_to_int_irrealizable_exitval_int64_min(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi double [ 2.500000e+01, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: call void @opaque()
; CHECK-NEXT: [[IV_NEXT]] = fadd double [[IV]], 1.700000e+01
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult double [[IV_NEXT]], 0xC3E0000000000000
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop

loop:
%iv = phi double [ 2.500000e+01, %entry ], [ %iv.next, %loop ]
call void @opaque()
%iv.next = fadd double %iv, 1.700000e+01
%cmp = fcmp ult double %iv.next, 0xC3E0000000000000
br i1 %cmp, label %exit, label %loop

exit:
ret void
}

declare void @opaque()
Loading