diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1240,7 +1240,18 @@ if (isa(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"); } diff --git a/clang/test/CodeGen/no-junk-ftrunc.c b/clang/test/CodeGen/no-junk-ftrunc.c --- a/clang/test/CodeGen/no-junk-ftrunc.c +++ b/clang/test/CodeGen/no-junk-ftrunc.c @@ -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; + double d = 1e20; + return (int)d != 1e20 && (unsigned)d != 1e20; } -