[gcc r14-8302] tree-switch-conversion: Bugfixes for _BitInt [PR113491]

Jakub Jelinek jakub@gcc.gnu.org
Sat Jan 20 11:37:23 GMT 2024


https://gcc.gnu.org/g:291e00e2d88a352f46cd539e3c5785982dc3fdd9

commit r14-8302-g291e00e2d88a352f46cd539e3c5785982dc3fdd9
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Jan 20 12:35:38 2024 +0100

    tree-switch-conversion: Bugfixes for _BitInt [PR113491]
    
    The following patch fixes various issues with large/huge _BitInt used as switch
    expressions.
    In particular:
    1) the indexes in CONSTRUCTORs shouldn't be types with precision larger than
       sizetype precision, varasm uses wi::to_offset on those and too large
       indexes ICE; we've already checked earlier that the cluster is at most
       sizetype bits and arrays can't be larger than that anyway
    2) some spots were using SCALAR_INT_TYPE_MODE or
       lang_hooks.types.type_for_mode on TYPE_MODE to determine types to use,
       that obviously doesn't work for the large/huge BITINT_TYPE
    3) like the recent change in the C FE, this patch makes sure we don't create
       ARRAY_REFs with indexes with precision above sizetype precision, because
       bitint lowering isn't prepared for that and because the indexes can't be
       larger than sizetype anyway; the subtraction of the cluster minimum from
       the index obviously needs to be done in unsigned __int128 or large/huge
       BITINT_TYPE, but then we cast to sizetype if the precision is larger than
       sizetype
    
    2024-01-20  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/113491
            * tree-switch-conversion.cc (switch_conversion::build_constructors):
            If elt.index has precision higher than sizetype, fold_convert it to
            sizetype.
            (switch_conversion::array_value_type): Return type if type is
            BITINT_TYPE with precision above MAX_FIXED_MODE_SIZE or with BLKmode.
            (switch_conversion::build_arrays): Use unsigned_type_for rather than
            lang_hooks.types.type_for_mode if utype is BITINT_TYPE with precision
            above MAX_FIXED_MODE_SIZE or with BLKmode.  If utype has precision
            higher than sizetype, use sizetype as tidx type and fold_convert the
            subtraction to sizetype.
    
            * gcc.dg/torture/bitint-51.c: New test.

Diff:
---
 gcc/testsuite/gcc.dg/torture/bitint-51.c | 88 ++++++++++++++++++++++++++++++++
 gcc/tree-switch-conversion.cc            | 24 +++++++--
 2 files changed, 109 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/bitint-51.c b/gcc/testsuite/gcc.dg/torture/bitint-51.c
new file mode 100644
index 00000000000..4c9ebc32cd3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bitint-51.c
@@ -0,0 +1,88 @@
+/* PR tree-optimization/113491 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+/* { dg-skip-if "" { ! run_expensive_tests }  { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __BITINT_MAXWIDTH__ >= 2022
+long a;
+_BitInt (2022) b;
+
+__attribute__((noipa)) void
+foo (void)
+{
+  long e;
+  switch (b)
+    {
+    case 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904587wb:
+      e = 28;
+      break;
+    case 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904590wb:
+      e = 6;
+      break;
+    case 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904607wb:
+      e = 7;
+      break;
+    default:
+      e = 8;
+      break;
+    }
+  a = e;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 2022
+  b = 42wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904586wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904587wb;
+  foo ();
+  if (a != 28)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904588wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904589wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904590wb;
+  foo ();
+  if (a != 6)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904591wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904606wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904607wb;
+  foo ();
+  if (a != 7)
+    __builtin_abort ();
+  b = 236881099392745653949476092019254703673343952653001806909505866172387514585208299669392000424755912461093218145058550533815207769064511922933470022995816097769135032744756688849360373090388143543095880516133276503510437474354615271669000583762291950374253494970691499065905744428004707234072154531557724197892702081481886955739280363415482836575783505023297999635820743287218509451775188374692338715173350419479853664808666850654180398109587878293637547258643044750595201236843385276543354061680674360041173237330198483330996131123489419291470122643730353591015638976897743657130063384289745055875469886904608wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = 240780458385579342400393461351617812815637161357071131707208942081962936661153218844512115504763375697200879163458183553026017242301187821441055479544760906104973534996069938628004474568289906582206917095065620305216254432816950650228843795794816095162791355341943390986975847866692139272448065870433527123346286515814575123941041341323886584452213168407427683905346733773730890398535581783579726464034446453496393589067919979673611753823620422962335479358086639875375670825770647896268644196740771259886611570273762180917307714137084771977480688440721015151914970095703226362506437887288273484956889253937151wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+  b = -240780458385579342400393461351617812815637161357071131707208942081962936661153218844512115504763375697200879163458183553026017242301187821441055479544760906104973534996069938628004474568289906582206917095065620305216254432816950650228843795794816095162791355341943390986975847866692139272448065870433527123346286515814575123941041341323886584452213168407427683905346733773730890398535581783579726464034446453496393589067919979673611753823620422962335479358086639875375670825770647896268644196740771259886611570273762180917307714137084771977480688440721015151914970095703226362506437887288273484956889253937151wb;
+  foo ();
+  if (a != 8)
+    __builtin_abort ();
+#endif
+  return 0;
+}
diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc
index 54aadf6b3bd..3a5b84c09e2 100644
--- a/gcc/tree-switch-conversion.cc
+++ b/gcc/tree-switch-conversion.cc
@@ -423,6 +423,9 @@ switch_conversion::build_constructors ()
 	      constructor_elt elt;
 
 	      elt.index = int_const_binop (MINUS_EXPR, pos, m_range_min);
+	      if (TYPE_PRECISION (TREE_TYPE (elt.index))
+		  > TYPE_PRECISION (sizetype))
+		elt.index = fold_convert (sizetype, elt.index);
 	      elt.value
 		= unshare_expr_without_location (m_default_values[k]);
 	      m_constructors[k]->quick_push (elt);
@@ -452,6 +455,9 @@ switch_conversion::build_constructors ()
 	      constructor_elt elt;
 
 	      elt.index = int_const_binop (MINUS_EXPR, pos, m_range_min);
+	      if (TYPE_PRECISION (TREE_TYPE (elt.index))
+		  > TYPE_PRECISION (sizetype))
+		elt.index = fold_convert (sizetype, elt.index);
 	      elt.value = unshare_expr_without_location (val);
 	      m_constructors[j]->quick_push (elt);
 
@@ -543,7 +549,10 @@ switch_conversion::array_value_type (tree type, int num)
 
   type = TYPE_MAIN_VARIANT (type);
 
-  if (!INTEGRAL_TYPE_P (type))
+  if (!INTEGRAL_TYPE_P (type)
+      || (TREE_CODE (type) == BITINT_TYPE
+	  && (TYPE_PRECISION (type) > MAX_FIXED_MODE_SIZE
+	      || TYPE_MODE (type) == BLKmode)))
     return type;
 
   scalar_int_mode type_mode = SCALAR_INT_TYPE_MODE (type);
@@ -707,7 +716,7 @@ void
 switch_conversion::build_arrays ()
 {
   tree arr_index_type;
-  tree tidx, sub, utype;
+  tree tidx, sub, utype, tidxtype;
   gimple *stmt;
   gimple_stmt_iterator gsi;
   gphi_iterator gpi;
@@ -720,14 +729,23 @@ switch_conversion::build_arrays ()
   utype = TREE_TYPE (m_index_expr);
   if (TREE_TYPE (utype))
     utype = lang_hooks.types.type_for_mode (TYPE_MODE (TREE_TYPE (utype)), 1);
+  else if (TREE_CODE (utype) == BITINT_TYPE
+	   && (TYPE_PRECISION (utype) > MAX_FIXED_MODE_SIZE
+	       || TYPE_MODE (utype) == BLKmode))
+    utype = unsigned_type_for (utype);
   else
     utype = lang_hooks.types.type_for_mode (TYPE_MODE (utype), 1);
+  if (TYPE_PRECISION (utype) > TYPE_PRECISION (sizetype))
+    tidxtype = sizetype;
+  else
+    tidxtype = utype;
 
   arr_index_type = build_index_type (m_range_size);
-  tidx = make_ssa_name (utype);
+  tidx = make_ssa_name (tidxtype);
   sub = fold_build2_loc (loc, MINUS_EXPR, utype,
 			 fold_convert_loc (loc, utype, m_index_expr),
 			 fold_convert_loc (loc, utype, m_range_min));
+  sub = fold_convert (tidxtype, sub);
   sub = force_gimple_operand_gsi (&gsi, sub,
 				  false, NULL, true, GSI_SAME_STMT);
   stmt = gimple_build_assign (tidx, sub);


More information about the Gcc-cvs mailing list