summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2011-12-31 00:15:06 -0200
committerQt by Nokia <qt-info@nokia.com>2012-03-24 19:07:22 +0100
commitad81f75429f6c5586d667880f90f4a425f1ce968 (patch)
tree543600f4a8d20c8be210a0008cc5ab4dd4116148 /src
parent4131c323a36ee8680a3b4d66a2a03a00544751c2 (diff)
Add macros for assuming and unreachable code
Use these macros to tell the compiler about conditions that may happen, so it will generate better code. But do not assume that they will do anything special. Change-Id: I89ec4f65f48a9340ccf5ffc4ae4b8c3d8897c8b1 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com> Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qcompilerdetection.h8
-rw-r--r--src/corelib/global/qglobal.cpp57
-rw-r--r--src/corelib/global/qglobal.h6
3 files changed, 71 insertions, 0 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index f3f0302072..c9f59454b2 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -88,6 +88,8 @@
# define Q_NO_TEMPLATE_FRIENDS
# define Q_ALIGNOF(type) __alignof(type)
# define Q_DECL_ALIGN(n) __declspec(align(n))
+# define Q_ASSUME(expr) __assume(expr)
+# define Q_UNREACHABLE() __assume(0)
/* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */
# if defined(__INTEL_COMPILER)
# define Q_CC_INTEL
@@ -141,11 +143,17 @@
# if defined(__INTEL_COMPILER)
/* Intel C++ also masquerades as GCC */
# define Q_CC_INTEL
+# define Q_ASSUME(expr) __assume(expr)
+# define Q_UNREACHABLE() __assume(0)
# elif defined(__clang__)
/* Clang also masquerades as GCC */
# define Q_CC_CLANG
+# define Q_ASSUME(expr) if (expr){} else __builtin_unreachable()
+# define Q_UNREACHABLE() __builtin_unreachable()
# else
/* Plain GCC */
+# define Q_ASSUME(expr) if (expr){} else __builtin_unreachable()
+# define Q_UNREACHABLE() __builtin_unreachable()
# endif
# define Q_ALIGNOF(type) __alignof__(type)
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 09d178639d..f89b0b3421 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1799,6 +1799,63 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion()
*/
/*!
+ \macro void Q_ASSUME(bool expr)
+ \relates <QtGlobal>
+ \since 5.0
+
+ Causes the compiler to assume that \a expr is true. This macro is useful
+ for improving code generation, by providing the compiler with hints about
+ conditions that it would not otherwise know about. However, there is no
+ guarantee that the compiler will actually use those hints.
+
+ This macro could be considered a "lighter" version of \ref Q_ASSERT. While
+ Q_ASSERT will abort the program's execution if the condition is false,
+ Q_ASSUME will tell the compiler not to generate code for those conditions.
+ Therefore, it is important that the assumptions always hold, otherwise
+ undefined behaviour may occur.
+
+ If \a expr is a constantly false condition, Q_ASSUME will tell the compiler
+ that the current code execution cannot be reached. That is, Q_ASSUME(false)
+ is equivalent to Q_UNREACHABLE().
+
+ \note Q_LIKELY() tells the compiler that the expression is likely, but not
+ the only possibility. Q_ASSUME tells the compiler that it is the only
+ possibility.
+
+ \sa Q_ASSERT(), Q_UNREACHABLE(), Q_LIKELY()
+*/
+
+/*!
+ \macro void Q_UNREACHABLE()
+ \relates <QtGlobal>
+ \since 5.0
+
+ Tells the compiler that the current point cannot be reached by any
+ execution, so it may optimise any code paths leading here as dead code, as
+ well as code continuing from here.
+
+ This macro is useful to mark impossible conditions. For example, given the
+ following enum:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp qunreachable-enum
+
+ One can write a switch table like so:
+
+ \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp qunreachable-switch
+
+ The advantage of inserting Q_UNREACHABLE() at that point is that the
+ compiler is told not to generate code for a shape variable containing that
+ value. If the macro is missing, the compiler will still generate the
+ necessary comparisons for that value. If the case label were removed, some
+ compilers could produce a warning that some enum values were not checked.
+
+ By using this macro in impossible conditions, code coverage may be improved
+ as dead code paths may be eliminated.
+
+ \sa Q_ASSERT(), Q_ASSUME(), qFatal()
+*/
+
+/*!
\macro void Q_CHECK_PTR(void *pointer)
\relates <QtGlobal>
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 734177638c..7d91fa3ca9 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -163,6 +163,12 @@ namespace QT_NAMESPACE {}
#ifndef Q_UNLIKELY
# define Q_UNLIKELY(x) (x)
#endif
+#ifndef Q_ASSUME
+# define Q_ASSUME(expr)
+#endif
+#ifndef Q_UNREACHABLE
+# define Q_UNREACHABLE()
+#endif
#ifndef Q_ALLOC_SIZE
# define Q_ALLOC_SIZE(x)