[PATCH] [ConstantFolding] Fix wrong folding of intrinsic 'convert.from.fp16'.
Andrea Di Biagio
Andrea_DiBiagio at sn.scee.net
Thu May 14 07:57:14 PDT 2015
Hi hfinkel, majnemer,
This patch fixes a wrong constant folding of intrinsic 'convert.from.fp16'.
Function 'ConstantFoldScalarCall' (in ConstantFolding.cpp) works under the wrong assumption that a call to 'convert.from.fp16' always returns a value of type 'float'.
However, intrinsic 'convert.from.fp16' can be 'overloaded'; for example, we can use 'convert.from.fp16.fp64' to convert from half to double; etc.
Before this patch, the following example would have triggered an assertion failure in opt (with '-constprop'):
```
define double @foo() {
entry:
%0 = call double @llvm.convert.from.fp16.f64(i16 0)
ret double %0
}
```
in Value.cpp:325: void llvm::Value::replaceAllUsesWith(llvm::Value*): Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!" failed.
This patch fixes the problem in ConstantFolding.cpp. When folding a call to convert.from.fp16, we perform a different kind of conversion based on the call return type.
Added test 'Transform/ConstProp/convert-from-fp16.ll'.
Please let me know if ok to submit.
Thanks!
-Andrea
http://reviews.llvm.org/D9771
Files:
lib/Analysis/ConstantFolding.cpp
test/Transforms/ConstProp/convert-from-fp16.ll
Index: lib/Analysis/ConstantFolding.cpp
===================================================================
--- lib/Analysis/ConstantFolding.cpp
+++ lib/Analysis/ConstantFolding.cpp
@@ -1397,6 +1397,25 @@
return APF.convertToDouble();
}
+// Returns the floating point arithmetic semantic associated to type 'Ty'.
+// This helper function is used by 'ConstantFoldScalarCall' when
+// constant folding intrinsic calls to 'convert_from_fp16'.
+static const fltSemantics &getFloatingPointSemanticFromType(const Type *Ty) {
+ if (Ty->isHalfTy())
+ return APFloat::IEEEhalf;
+ else if (Ty->isFloatTy())
+ return APFloat::IEEEsingle;
+ else if (Ty->isDoubleTy())
+ return APFloat::IEEEdouble;
+ else if (Ty->isFP128Ty())
+ return APFloat::IEEEquad;
+ else if (Ty->isX86_FP80Ty())
+ return APFloat::x87DoubleExtended;
+ else if (Ty->isPPC_FP128Ty())
+ return APFloat::PPCDoubleDouble;
+ llvm_unreachable("Not a floating point type!");
+}
+
static Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID,
Type *Ty, ArrayRef<Constant *> Operands,
const TargetLibraryInfo *TLI) {
@@ -1543,8 +1562,10 @@
APFloat Val(APFloat::IEEEhalf, Op->getValue());
bool lost = false;
+
+ const fltSemantics &FPS = getFloatingPointSemanticFromType(Ty);
APFloat::opStatus status =
- Val.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &lost);
+ Val.convert(FPS, APFloat::rmNearestTiesToEven, &lost);
// Conversion is always precise.
(void)status;
Index: test/Transforms/ConstProp/convert-from-fp16.ll
===================================================================
--- test/Transforms/ConstProp/convert-from-fp16.ll
+++ test/Transforms/ConstProp/convert-from-fp16.ll
@@ -0,0 +1,45 @@
+; RUN: opt -constprop -S < %s | FileCheck %s
+
+; Verify that we don't crash with an assertion failure when constant folding
+; a call to intrinsic 'convert.from.fp16' if the return type is not 'float'.
+
+define float @fold_from_fp16_to_fp32() {
+; CHECK: ret float 0.000000e+00
+entry:
+ %0 = call float @llvm.convert.from.fp16.f32(i16 0)
+ ret float %0
+}
+
+define double @fold_from_fp16_to_fp64() {
+; CHECK: ret double 0.000000e+00
+entry:
+ %0 = call double @llvm.convert.from.fp16.f64(i16 0)
+ ret double %0
+}
+
+define x86_fp80 @fold_from_fp16_to_fp80() {
+; CHECK: ret x86_fp80 0xK00000000000000000000
+entry:
+ %0 = call x86_fp80 @llvm.convert.from.fp16.f80(i16 0)
+ ret x86_fp80 %0
+}
+
+define fp128 @fold_from_fp16_to_fp128() {
+; CHECK: ret fp128 0xL00000000000000000000000000000000
+entry:
+ %0 = call fp128 @llvm.convert.from.fp16.f128(i16 0)
+ ret fp128 %0
+}
+
+define ppc_fp128 @fold_from_fp16_to_ppcfp128() {
+; CHECK: ret ppc_fp128 0xM00000000000000000000000000000000
+entry:
+ %0 = call ppc_fp128 @llvm.convert.from.fp16.ppcf128(i16 0)
+ ret ppc_fp128 %0
+}
+
+declare float @llvm.convert.from.fp16.f32(i16)
+declare double @llvm.convert.from.fp16.f64(i16)
+declare x86_fp80 @llvm.convert.from.fp16.f80(i16)
+declare fp128 @llvm.convert.from.fp16.f128(i16)
+declare ppc_fp128 @llvm.convert.from.fp16.ppcf128(i16)
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D9771.25776.patch
Type: text/x-patch
Size: 3230 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150514/9bca9748/attachment.bin>
More information about the llvm-commits
mailing list