Skip to content

Commit 1261c5a

Browse files
[IndVarSimplify] Ensure fp values can be represented as consecutive integers
When transforming floating-point induction variables into integer ones, make sure we stay within the bounds of fp values that can be represented as integers without gaps, i.e., 2^24 and 2^53 for IEEE-754 single and double precision respectively (both on negative and positive side). Fixes: #166496.
1 parent 8a2ef91 commit 1261c5a

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

llvm/lib/Transforms/Scalar/IndVarSimplify.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,21 @@ bool IndVarSimplify::handleFloatingPointIV(Loop *L, PHINode *PN) {
228228
!ConvertToSInt(IncValueVal->getValueAPF(), IncValue))
229229
return false;
230230

231+
// Ensure we stay within the bounds of fp values that can be represented
232+
// as integers without gaps, i.e., 2^24 and 2^53 for IEEE-754 single and
233+
// double precision respectively (both on negative and positive side).
234+
const auto &SVFltSema = InitValueVal->getValueAPF().getSemantics();
235+
if (!APFloat::isIEEELikeFP(SVFltSema))
236+
return false;
237+
238+
uint64_t StartValPrecision = APFloat::semanticsPrecision(SVFltSema);
239+
if (StartValPrecision >= 64)
240+
return false;
241+
242+
uint64_t StartValIntegerLimit = 1LL << StartValPrecision;
243+
if (uint64_t(std::abs(InitValue)) > StartValIntegerLimit)
244+
return false;
245+
231246
// Check Incr uses. One user is PN and the other user is an exit condition
232247
// used by the conditional terminator.
233248
Value::user_iterator IncrUse = Incr->user_begin();
@@ -265,6 +280,18 @@ bool IndVarSimplify::handleFloatingPointIV(Loop *L, PHINode *PN) {
265280
!ConvertToSInt(ExitValueVal->getValueAPF(), ExitValue))
266281
return false;
267282

283+
const auto &EVFltSema = ExitValueVal->getValueAPF().getSemantics();
284+
if (!APFloat::isIEEELikeFP(EVFltSema))
285+
return false;
286+
287+
uint64_t ExitValPrecision = APFloat::semanticsPrecision(EVFltSema);
288+
if (ExitValPrecision >= 64)
289+
return false;
290+
291+
uint64_t ExitValIntegerLimit = 1LL << ExitValPrecision;
292+
if (uint64_t(std::abs(ExitValue)) > ExitValIntegerLimit)
293+
return false;
294+
268295
// Find new predicate for integer comparison.
269296
CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE;
270297
switch (Compare->getPredicate()) {

llvm/test/Transforms/IndVarSimplify/floating-point-iv.ll

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -418,16 +418,15 @@ exit:
418418
ret void
419419
}
420420

421-
; FIXME: These are miscompilation issues.
422421
define void @test_fp_to_int_irrealizable_initval() {
423422
; CHECK-LABEL: @test_fp_to_int_irrealizable_initval(
424423
; CHECK-NEXT: entry:
425424
; CHECK-NEXT: br label [[LOOP:%.*]]
426425
; CHECK: loop:
427-
; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100000000, [[ENTRY:%.*]] ], [ [[IV_NEXT_INT:%.*]], [[LOOP]] ]
426+
; CHECK-NEXT: [[IV:%.*]] = phi float [ 1.000000e+08, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
428427
; CHECK-NEXT: call void @opaque()
429-
; CHECK-NEXT: [[IV_NEXT_INT]] = add nsw i32 [[IV_INT]], -17
430-
; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[IV_NEXT_INT]], 25
428+
; CHECK-NEXT: [[IV_NEXT]] = fadd float [[IV]], -1.700000e+01
429+
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult float [[IV_NEXT]], 2.500000e+01
431430
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
432431
; CHECK: exit:
433432
; CHECK-NEXT: ret void
@@ -451,10 +450,10 @@ define void @test_fp_to_int_irrealizable_exitval() {
451450
; CHECK-NEXT: entry:
452451
; CHECK-NEXT: br label [[LOOP:%.*]]
453452
; CHECK: loop:
454-
; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 25, [[ENTRY:%.*]] ], [ [[IV_NEXT_INT:%.*]], [[LOOP]] ]
453+
; CHECK-NEXT: [[IV:%.*]] = phi float [ 2.500000e+01, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
455454
; CHECK-NEXT: call void @opaque()
456-
; CHECK-NEXT: [[IV_NEXT_INT]] = add nuw nsw i32 [[IV_INT]], 17
457-
; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[IV_NEXT_INT]], 100000000
455+
; CHECK-NEXT: [[IV_NEXT]] = fadd float [[IV]], 1.700000e+01
456+
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[IV_NEXT]], 1.000000e+08
458457
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
459458
; CHECK: exit:
460459
; CHECK-NEXT: ret void
@@ -478,10 +477,10 @@ define void @test_fp_to_int_irrealizable_negative_exitval() {
478477
; CHECK-NEXT: entry:
479478
; CHECK-NEXT: br label [[LOOP:%.*]]
480479
; CHECK: loop:
481-
; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ -25, [[ENTRY:%.*]] ], [ [[IV_NEXT_INT:%.*]], [[LOOP]] ]
480+
; CHECK-NEXT: [[IV:%.*]] = phi float [ -2.500000e+01, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
482481
; CHECK-NEXT: call void @opaque()
483-
; CHECK-NEXT: [[IV_NEXT_INT]] = add nsw i32 [[IV_INT]], -17
484-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_NEXT_INT]], -100000000
482+
; CHECK-NEXT: [[IV_NEXT]] = fadd float [[IV]], -1.700000e+01
483+
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult float [[IV_NEXT]], -1.000000e+08
485484
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
486485
; CHECK: exit:
487486
; CHECK-NEXT: ret void

0 commit comments

Comments
 (0)