[CodeGen] use saturating FP casts when compiling with "no-strict-float-cast-overflow"
We got an unintended consequence of the optimizer getting smarter when compiling in a non-standard mode, and there's no good way to inhibit those optimizations at a later stage. The test is based on an example linked from D92270. We allow the "no-strict-float-cast-overflow" exception to normal C cast rules to preserve legacy code that does not expect overflowing casts from FP to int to produce UB. See D46236 for details. Differential Revision: https://reviews.llvm.org/D115804
This commit is contained in:
@@ -1240,7 +1240,18 @@ Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
|
||||
|
||||
if (isa<llvm::IntegerType>(DstElementTy)) {
|
||||
assert(SrcElementTy->isFloatingPointTy() && "Unknown real conversion");
|
||||
if (DstElementType->isSignedIntegerOrEnumerationType())
|
||||
bool IsSigned = DstElementType->isSignedIntegerOrEnumerationType();
|
||||
|
||||
// If we can't recognize overflow as undefined behavior, assume that
|
||||
// overflow saturates. This protects against normal optimizations if we are
|
||||
// compiling with non-standard FP semantics.
|
||||
if (!CGF.CGM.getCodeGenOpts().StrictFloatCastOverflow) {
|
||||
llvm::Intrinsic::ID IID =
|
||||
IsSigned ? llvm::Intrinsic::fptosi_sat : llvm::Intrinsic::fptoui_sat;
|
||||
return Builder.CreateCall(CGF.CGM.getIntrinsic(IID, {DstTy, SrcTy}), Src);
|
||||
}
|
||||
|
||||
if (IsSigned)
|
||||
return Builder.CreateFPToSI(Src, DstTy, "conv");
|
||||
return Builder.CreateFPToUI(Src, DstTy, "conv");
|
||||
}
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
// RUN: %clang_cc1 -S -fno-strict-float-cast-overflow %s -emit-llvm -o - | FileCheck %s --check-prefix=NOSTRICT
|
||||
|
||||
// When compiling with non-standard semantics, use intrinsics to inhibit the optimizer.
|
||||
|
||||
// NOSTRICT-LABEL: main
|
||||
// NOSTRICT: call i32 @llvm.fptosi.sat.i32.f64
|
||||
// NOSTRICT: call i32 @llvm.fptoui.sat.i32.f64
|
||||
// NOSTRICT: attributes #0 = {{.*}}"strict-float-cast-overflow"="false"{{.*}}
|
||||
|
||||
// The workaround attribute is not applied by default.
|
||||
|
||||
// RUN: %clang_cc1 -S %s -emit-llvm -o - | FileCheck %s --check-prefix=STRICT
|
||||
// STRICT-LABEL: main
|
||||
// STRICT: = fptosi
|
||||
// STRICT: = fptoui
|
||||
// STRICT-NOT: strict-float-cast-overflow
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
double d = 1e20;
|
||||
return (int)d != 1e20 && (unsigned)d != 1e20;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user