leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.
Herald added a subscriber: mgorny.

This patch includes checks that the precision macros used for the fixed point 
fractional and integral bits meet the requirements for clause 6.2.6.3 in 
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf.

Checks for any disagreements with the recommendations will throw warnings.

I also added my own warning that recommends the integral and fractional bits 
for _Accum types take up the width of the whole underlying integer to prevent 
having to mask out the padding bits when performing comparisons.


Repository:
  rC Clang

https://reviews.llvm.org/D47030

Files:
  cmake/modules/InitFixedPointBits.cmake

Index: cmake/modules/InitFixedPointBits.cmake
===================================================================
--- cmake/modules/InitFixedPointBits.cmake
+++ cmake/modules/InitFixedPointBits.cmake
@@ -60,26 +60,170 @@
   set(ULACCUM_IBIT 32)
 endif()
 
-# Checks for each bit size
+# Checks for each bit size defined in clause 6.2.6.3
+
+# Cannot go below the minimum number of fractional and integral bits for the
+# various types specified in clause 7.18a.3.
+function(assert_min_bits macro min_bits)
+  set("macro_name" ${macro})
+  set("macro_val" ${${macro}})
+  if(${macro_val} LESS ${min_bits})
+    message(FATAL_ERROR "The minimum value allowed for ${macro_name} is ${min_bits}. "
+	    "${macro_val} was provided.")
+  endif()
+endfunction()
+
+assert_min_bits(SFRACT_FBIT 7)
+assert_min_bits(FRACT_FBIT 15)
+assert_min_bits(LFRACT_FBIT 23)
+assert_min_bits(USFRACT_FBIT 7)
+assert_min_bits(UFRACT_FBIT 15)
+assert_min_bits(ULFRACT_FBIT 23)
+
+assert_min_bits(SACCUM_FBIT 7)
+assert_min_bits(ACCUM_FBIT 15)
+assert_min_bits(LACCUM_FBIT 23)
+assert_min_bits(USACCUM_FBIT 7)
+assert_min_bits(UACCUM_FBIT 15)
+assert_min_bits(ULACCUM_FBIT 23)
+
+assert_min_bits(SACCUM_IBIT 4)
+assert_min_bits(ACCUM_IBIT 4)
+assert_min_bits(LACCUM_IBIT 4)
+assert_min_bits(USACCUM_IBIT 4)
+assert_min_bits(UACCUM_IBIT 4)
+assert_min_bits(ULACCUM_IBIT 4)
+
 # Each unsigned fract type has either the same number of fractional bits as,
 # or one more fractional bit than, its corresponding signed fract type.
-# TODO: Implement remaining checks in clause 6.2.6.3.
-function(check_diff_at_most_1 sfract_fbits ufract_fbits)
-  if(sfract_fbits EQUAL ufract_fbits)
-    return()
-  endif()
+function(assert_fract_diff sfract_fbits ufract_fbits)
   math(EXPR diff "${ufract_fbits} - ${sfract_fbits}")
-  if(diff EQUAL 1)
-    return()
+  if(NOT((${diff} EQUAL 0) OR (${diff} EQUAL 1)))
+    message(FATAL_ERROR "Each unsigned fract type must have either the same number of "
+  	    "fractional bits as, or one more fractional bit than, its corresponding "
+  	    "signed fract type.")
+  endif()
+endfunction()
+
+assert_fract_diff(${SFRACT_FBIT} ${USFRACT_FBIT})
+assert_fract_diff(${FRACT_FBIT} ${UFRACT_FBIT})
+assert_fract_diff(${LFRACT_FBIT} ${ULFRACT_FBIT})
+
+# When arranged in order of increasing rank (see 6.3.1.3a), the number of
+# fractional bits is nondecreasing for each of the following sets of
+# fixed-point types:
+# - signed fract types
+# - unsigned fract types
+# - signed accum types
+# - unsigned accum types.
+function(assert_non_decreasing short_type_bits middle_type_bits long_type_bits
+	 type_family bit_type)
+  if((${short_type_bits} GREATER ${middle_type_bits}) OR
+     (${middle_type_bits} GREATER ${long_type_bits}))
+    message(FATAL_ERROR "The number of ${bit_type} bits in ${type_family} types must be "
+  	    "non decreasing in order of increasing rank.")
+  endif()
+endfunction()
+
+assert_non_decreasing(${SFRACT_FBIT} ${FRACT_FBIT} ${LFRACT_FBIT} "signed _Fract" "fractional")
+assert_non_decreasing(${USFRACT_FBIT} ${UFRACT_FBIT} ${ULFRACT_FBIT} "unsigned _Fract" "fractional")
+assert_non_decreasing(${SACCUM_FBIT} ${ACCUM_FBIT} ${LACCUM_FBIT} "signed _Accum" "fractional")
+assert_non_decreasing(${USACCUM_FBIT} ${UACCUM_FBIT} ${ULACCUM_FBIT} "unsigned _Accum" "fractional")
+
+# When arranged in order of increasing rank (see 6.3.1.3a), the number of
+# integral bits is nondecreasing for each of the following sets of
+# fixed-point types:
+# - signed accum types
+# - unsigned accum types.
+assert_non_decreasing(${SACCUM_IBIT} ${ACCUM_IBIT} ${LACCUM_IBIT} "signed _Accum" "integral")
+assert_non_decreasing(${USACCUM_IBIT} ${UACCUM_IBIT} ${ULACCUM_IBIT} "unsigned _Accum" "integral")
+
+# Each signed accum type has at least as many integral bits as its
+# corresponding unsigned accum type.
+function(assert_integral_diff saccum_ibits uaccum_ibits)
+  if(${saccum_ibits} LESS ${uaccum_ibits})
+    message(FATAL_ERROR "Each signed accum type must have at least as many integral bits as its "
+	    "corresponding unsigned accum type.")
+  endif()
+endfunction()
+
+assert_integral_diff(${SACCUM_IBIT} ${USACCUM_IBIT})
+assert_integral_diff(${ACCUM_IBIT} ${UACCUM_IBIT})
+assert_integral_diff(${LACCUM_IBIT} ${ULACCUM_IBIT})
+
+# The following checks are not required, bit recommended to promote consistency
+# amongst implementations.
+
+# The signed long _Fract type has at least 31 fractional bits
+if(${LFRACT_FBIT} LESS 31)
+  message(WARNING "It is recommended that the signed long _Fract type has at least 31 "
+	  "fractional bits")
+endif()
+
+# Each accum type has at least 8 integral bits
+function(check_accum_ibits accum_ibits)
+  if(${accum_ibits} LESS 8)
+    message(WARNING "It is recommended that each accum type has at least 8 integral bits")
+  endif()
+endfunction()
+
+check_accum_ibits(${SACCUM_IBIT})
+check_accum_ibits(${ACCUM_IBIT})
+check_accum_ibits(${LACCUM_IBIT})
+check_accum_ibits(${USACCUM_IBIT})
+check_accum_ibits(${UACCUM_IBIT})
+check_accum_ibits(${ULACCUM_IBIT})
+
+# Each unsigned accum type has the same number of fractional bits as its corresponding
+# unsigned fract type.
+function(check_unsigned_fract_diff uaccum_fbits ufract_fbits)
+  if(NOT(${uaccum_fbits} EQUAL ${ufract_fbits}))
+    message(WARNING "It is recommended that each unsigned accum type have the same "
+	    "number of fractional bits as its corresponding unsigned fract type.")
+  endif()
+endfunction()
+
+check_unsigned_fract_diff(${USACCUM_FBIT} ${USFRACT_FBIT})
+check_unsigned_fract_diff(${UACCUM_FBIT} ${UFRACT_FBIT})
+check_unsigned_fract_diff(${ULACCUM_FBIT} ${ULFRACT_FBIT})
+
+# Each signed accum type has the same number of fractional bits as either its
+# corresponding signed fract type or its corresponding unsigned fract type.
+function(check_signed_fract_diff saccum_fbits sfract_fbits)
+  if(NOT(${saccum_fbits} EQUAL ${sfract_fbits}))
+    message(WARNING "It is recommended that each unsigned accum type have the same "
+	    "number of fractional bits as its corresponding unsigned fract type.")
+  endif()
+endfunction()
+
+# Not part of N1169 but can help with some optimizations by not having to mask or reset
+# any padding bits on operations that involve reading from them. For example, if a short
+# _Accum type has 7 fractional bits, 4 integral bits, 1 sign bit, and is stored in a 16
+# bit integer, there will be 4 padding bits left in the int. When performing normal
+# arithmetic operations like addition, we can normally ignore these bits, but for operations
+# that involve reading the entire bit width like equality, these padding bits will be read.
+# They will need to be ignored either by zeroing them out if the fixed point type is
+# unsigned, or extending the sign with a shift left then shift right into the padding.
+#
+# Having no padding can allow for ignoring these instructions on _Accum types. This won't
+# apply to _Fract types since they normally have padding by having no integral part.
+# One can technically extend the _Fract FBITS to take up the whole integer width to avoid
+# padding, but this is not recommended since they may not have the same number of fractional
+# bits for their corresponding _Accum types.
+function(check_bits_fill_int ibits fbits sign bit_width)
+  math(EXPR num_bits "${ibits} + ${fbits} + ${sign}")
+  if(NOT(${num_bits} EQUAL ${bit_width}))
+    message(WARNING "It is recommended that the number of fractional, integral, "
+  	    "and sign bits fill the whole width of the integer for some optimizations.")
   endif()
-  message(FATAL_ERROR "Each unsigned fract type has either the same number of "
-	  "fractional bits as, or one more fractional bit than, its corresponding "
-	  "signed fract type.")
 endfunction()
 
-check_diff_at_most_1(${SFRACT_FBIT} ${USFRACT_FBIT})
-check_diff_at_most_1(${FRACT_FBIT} ${UFRACT_FBIT})
-check_diff_at_most_1(${LFRACT_FBIT} ${ULFRACT_FBIT})
+check_bits_fill_int(${SACCUM_IBIT} ${SACCUM_FBIT} 1 16)
+check_bits_fill_int(${ACCUM_IBIT} ${ACCUM_FBIT} 1 32)
+check_bits_fill_int(${LACCUM_IBIT} ${LACCUM_FBIT} 1 64)
+check_bits_fill_int(${USACCUM_IBIT} ${USACCUM_FBIT} 0 16)
+check_bits_fill_int(${UACCUM_IBIT} ${UACCUM_FBIT} 0 32)
+check_bits_fill_int(${ULACCUM_IBIT} ${ULACCUM_FBIT} 0 64)
 
 # Configure the FixedPoint.h file.
 configure_file(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to