mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 22:20:37 +00:00
Make APFloat->int conversions deterministic even in
cases with undefined behavior. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42328 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7086ce7268
commit
0edc47ad7b
@ -1399,13 +1399,28 @@ APFloat::convertToInteger(integerPart *parts, unsigned int width,
|
||||
unsigned int msb, partsCount;
|
||||
int bits;
|
||||
|
||||
/* Handle the three special cases first. */
|
||||
if(category == fcInfinity || category == fcNaN)
|
||||
return opInvalidOp;
|
||||
|
||||
partsCount = partCountForBits(width);
|
||||
|
||||
if(category == fcZero) {
|
||||
/* Handle the three special cases first. We produce
|
||||
a deterministic result even for the Invalid cases. */
|
||||
if (category == fcNaN) {
|
||||
// Neither sign nor isSigned affects this.
|
||||
APInt::tcSet(parts, 0, partsCount);
|
||||
return opInvalidOp;
|
||||
}
|
||||
if (category == fcInfinity) {
|
||||
if (!sign && isSigned)
|
||||
APInt::tcSetLeastSignificantBits(parts, partsCount, width-1);
|
||||
else if (!sign && !isSigned)
|
||||
APInt::tcSetLeastSignificantBits(parts, partsCount, width);
|
||||
else if (sign && isSigned) {
|
||||
APInt::tcSetLeastSignificantBits(parts, partsCount, 1);
|
||||
APInt::tcShiftLeft(parts, partsCount, width-1);
|
||||
} else // sign && !isSigned
|
||||
APInt::tcSet(parts, 0, partsCount);
|
||||
return opInvalidOp;
|
||||
}
|
||||
if (category == fcZero) {
|
||||
APInt::tcSet(parts, 0, partsCount);
|
||||
return opOK;
|
||||
}
|
||||
@ -1418,6 +1433,19 @@ APFloat::convertToInteger(integerPart *parts, unsigned int width,
|
||||
if(bits > 0) {
|
||||
lost_fraction = tmp.shiftSignificandRight(bits);
|
||||
} else {
|
||||
if (-bits >= semantics->precision) {
|
||||
// Unrepresentably large.
|
||||
if (!sign && isSigned)
|
||||
APInt::tcSetLeastSignificantBits(parts, partsCount, width-1);
|
||||
else if (!sign && !isSigned)
|
||||
APInt::tcSetLeastSignificantBits(parts, partsCount, width);
|
||||
else if (sign && isSigned) {
|
||||
APInt::tcSetLeastSignificantBits(parts, partsCount, 1);
|
||||
APInt::tcShiftLeft(parts, partsCount, width-1);
|
||||
} else // sign && !isSigned
|
||||
APInt::tcSet(parts, 0, partsCount);
|
||||
return (opStatus)(opOverflow | opInexact);
|
||||
}
|
||||
tmp.shiftSignificandLeft(-bits);
|
||||
lost_fraction = lfExactlyZero;
|
||||
}
|
||||
|
@ -197,8 +197,6 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V,
|
||||
APFloat::opStatus status = V.convertToInteger(x, DestBitWidth,
|
||||
opc==Instruction::FPToSI,
|
||||
APFloat::rmTowardZero);
|
||||
if (status!=APFloat::opOK && status!=APFloat::opInexact)
|
||||
return 0; // give up
|
||||
APInt Val(DestBitWidth, 2, x);
|
||||
return ConstantInt::get(Val);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user