Skip to content

Commit 77c61ed

Browse files
committed
[Float2Int] Fix miscompile with floats that can be converted to large values
There is an issue with Float2Int whenever it has to deal with floats that evaluate to numbers that are over INT_MAX, but under UINT_MAX. Simply, because the conversion method always assumes a signed integer, this works until the 32 bit number is actually a positive 32 bit number that would be interpreted as a negative number when evaluated as an integer, being put in an i32. This was messing up the Float2Int conversions and causing miscompiles. To fix this, tell the APSInt constructor if the value is positive or negative.
1 parent 06e90c8 commit 77c61ed

File tree

2 files changed

+5
-6
lines changed

2 files changed

+5
-6
lines changed

llvm/lib/Transforms/Scalar/Float2Int.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,11 +409,10 @@ Value *Float2IntPass::convert(Instruction *I, Type *ToTy) {
409409
} else if (Instruction *VI = dyn_cast<Instruction>(V)) {
410410
NewOperands.push_back(convert(VI, ToTy));
411411
} else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
412-
APSInt Val(ToTy->getPrimitiveSizeInBits(), /*isUnsigned=*/false);
412+
const APFloat &F = CF->getValueAPF();
413+
APSInt Val(ToTy->getPrimitiveSizeInBits(), !F.isNegative());
413414
bool Exact;
414-
CF->getValueAPF().convertToInteger(Val,
415-
APFloat::rmNearestTiesToEven,
416-
&Exact);
415+
F.convertToInteger(Val, APFloat::rmNearestTiesToEven, &Exact);
417416
NewOperands.push_back(ConstantInt::get(ToTy, Val));
418417
} else {
419418
llvm_unreachable("Unhandled operand type?");

llvm/test/Transforms/Float2Int/basic.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ define i32 @pr79158() {
359359
; CHECK-NEXT: [[X_I_0_X_I_0_X_0_X_0_X_0__I:%.*]] = load volatile i32, ptr [[X_I]], align 4
360360
; CHECK-NEXT: [[CMP_I:%.*]] = icmp sgt i32 [[X_I_0_X_I_0_X_0_X_0_X_0__I]], 0
361361
; CHECK-NEXT: [[TMP0:%.*]] = zext i1 [[CMP_I]] to i32
362-
; CHECK-NEXT: [[MUL_I1:%.*]] = mul i32 [[TMP0]], 2147483647
362+
; CHECK-NEXT: [[MUL_I1:%.*]] = mul i32 [[TMP0]], -1
363363
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X_I]])
364364
; CHECK-NEXT: ret i32 0
365365
;
@@ -385,7 +385,7 @@ define i32 @pr79158_2() {
385385
; CHECK-NEXT: [[X_I_0_X_I_0_X_0_X_0_X_0__I:%.*]] = load volatile i32, ptr [[X_I]], align 4
386386
; CHECK-NEXT: [[CMP_I:%.*]] = icmp sgt i32 [[X_I_0_X_I_0_X_0_X_0_X_0__I]], 0
387387
; CHECK-NEXT: [[TMP0:%.*]] = zext i1 [[CMP_I]] to i32
388-
; CHECK-NEXT: [[MUL_I1:%.*]] = mul i32 [[TMP0]], 2147483647
388+
; CHECK-NEXT: [[MUL_I1:%.*]] = mul i32 [[TMP0]], -2147483648
389389
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X_I]])
390390
; CHECK-NEXT: ret i32 0
391391
;

0 commit comments

Comments
 (0)