summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-04-20 15:07:55 +0000
committerSanjay Patel <spatel@rotateright.com>2018-04-20 15:07:55 +0000
commit3d453ad7118a4be0fe5089ae6b3d1985ad5d1860 (patch)
treee25c6149445209635104f05858927d8bed22d03a /llvm/lib/CodeGen
parent863ffeb7509d9168578f2142c82943124394f274 (diff)
downloadbcm5719-llvm-3d453ad7118a4be0fe5089ae6b3d1985ad5d1860.tar.gz
bcm5719-llvm-3d453ad7118a4be0fe5089ae6b3d1985ad5d1860.zip
[DAGCombine] (float)((int) f) --> ftrunc (PR36617)
This was originally committed at rL328921 and reverted at rL329920 to investigate failures in Chrome. This time I've added to the ReleaseNotes to warn users of the potential of exposing UB and let me repeat that here for more exposure: Optimization of floating-point casts is improved. This may cause surprising results for code that is relying on undefined behavior. Code sanitizers can be used to detect affected patterns such as this: int main() { float x = 4294967296.0f; x = (float)((int)x); printf("junk in the ftrunc: %f\n", x); return 0; } $ clang -O1 ftrunc.c -fsanitize=undefined ; ./a.out ftrunc.c:5:15: runtime error: 4.29497e+09 is outside the range of representable values of type 'int' junk in the ftrunc: 0.000000 Original commit message: fptosi / fptoui round towards zero, and that's the same behavior as ISD::FTRUNC, so replace a pair of casts with the equivalent node. We don't have to account for special cases (NaN, INF) because out-of-range casts are undefined. Differential Revision: https://reviews.llvm.org/D44909 llvm-svn: 330437
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index abb25fb4f27..879e45df598 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -10890,6 +10890,15 @@ SDValue DAGCombiner::visitSINT_TO_FP(SDNode *N) {
}
}
+ // fptosi rounds towards zero, so converting from FP to integer and back is
+ // the same as an 'ftrunc': sitofp (fptosi X) --> ftrunc X
+ // We only do this if the target has legal ftrunc, otherwise we'd likely be
+ // replacing casts with a libcall.
+ if (N0.getOpcode() == ISD::FP_TO_SINT &&
+ N0.getOperand(0).getValueType() == VT &&
+ TLI.isOperationLegal(ISD::FTRUNC, VT))
+ return DAG.getNode(ISD::FTRUNC, SDLoc(N), VT, N0.getOperand(0));
+
return SDValue();
}
@@ -10929,6 +10938,15 @@ SDValue DAGCombiner::visitUINT_TO_FP(SDNode *N) {
}
}
+ // fptoui rounds towards zero, so converting from FP to integer and back is
+ // the same as an 'ftrunc': uitofp (fptoui X) --> ftrunc X
+ // We only do this if the target has legal ftrunc, otherwise we'd likely be
+ // replacing casts with a libcall.
+ if (N0.getOpcode() == ISD::FP_TO_UINT &&
+ N0.getOperand(0).getValueType() == VT &&
+ TLI.isOperationLegal(ISD::FTRUNC, VT))
+ return DAG.getNode(ISD::FTRUNC, SDLoc(N), VT, N0.getOperand(0));
+
return SDValue();
}
OpenPOWER on IntegriCloud