[rs6000] Fix PR83926, ICE using __builtin_vsx_{div,udiv,mul}_2di builtins

Message ID db769be5-cc5b-c17e-388c-0f58a4cc665d@vnet.ibm.com
State New
Headers show
Series
  • [rs6000] Fix PR83926, ICE using __builtin_vsx_{div,udiv,mul}_2di builtins
Related show

Commit Message

Peter Bergner Feb. 6, 2018, 12:07 a.m.
PR83926 shows a problem in expanding the _builtin_vsx_{div,udiv,mul}_2di
builtins in 32-bit mode.  The problem is that the splitters for the
patterns explicitly call gen_{div,udiv,mul}di3 patterns, even in 32-bit
mode and those patterns assume the associated 64-bit HW instructions exist
when they do not.  The "fix" implemented here is to modify gen_{div,udiv,mul}
to catch the case when we have DImode operands in 32-bit mode (and not using
-mpowerpc64) and do the right thing.  In the case of gen_{div,udiv}di3, that
means calling their lib functions and for gen_muldi3, we call expand_mult()
which emits code that does the 64-bit multiply.

This passes bootstrap and regtesting on powerpc64le-linux, as well as on
powerpc64-linux (running the testsuite in both 32-bit and 64-bit modes).
Ok for trunk?

Peter

gcc/
	PR target/83926
	* config/rs6000/rs6000.md (*mul<mode>3): Rename to this...
	(mul<mode>3): ...from this.  Declare new define_expand.
	(*udiv<mode>3): Rename to this...
	(udiv<mode>3): ...from this.  Declare new define_expand.
	(div<mode>3): Handle DImode operands in 32-bit mode.

gcc/testsuite/
	PR target/83926
	* gcc.target/powerpc/pr83926.c: New test.

Patch

Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 257390)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -2872,8 +2872,21 @@ 
   DONE;
 }")
 
+(define_expand "mul<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+	(mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+		  (match_operand:GPR 2 "reg_or_short_operand" "")))]
+  ""
+{
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rtx ret = expand_mult (DImode, operands[1], operands[2], NULL, 0, false);
+      emit_move_insn (operands[0], ret);    
+      DONE;
+    }
+})
 
-(define_insn "mul<mode>3"
+(define_insn "*mul<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
 	(mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
 		  (match_operand:GPR 2 "reg_or_short_operand" "r,I")))]
@@ -3040,7 +3053,25 @@ 
   "maddld %0,%1,%2,%3"
   [(set_attr "type" "mul")])
 
-(define_insn "udiv<mode>3"
+(define_expand "udiv<mode>3"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+	(udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+		  (match_operand:GPR 2 "gpc_reg_operand" "")))]
+  ""
+{
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rtx libfunc = optab_libfunc (udiv_optab, <MODE>mode);
+      rtx target = emit_library_call_value (libfunc,
+					    operands[0], LCT_NORMAL, <MODE>mode,
+					    operands[1], <MODE>mode,
+					    operands[2], <MODE>mode);
+      emit_move_insn (operands[0], target);    
+      DONE;
+    }
+})
+
+(define_insn "*udiv<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
         (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
 		  (match_operand:GPR 2 "gpc_reg_operand" "r")))]
@@ -3066,7 +3097,16 @@ 
       emit_insn (gen_div<mode>3_sra (operands[0], operands[1], operands[2]));
       DONE;
     }
-
+  else if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rtx libfunc = optab_libfunc (sdiv_optab, <MODE>mode);
+      rtx target = emit_library_call_value (libfunc,
+					    operands[0], LCT_NORMAL, <MODE>mode,
+					    operands[1], <MODE>mode,
+					    operands[2], <MODE>mode);
+      emit_move_insn (operands[0], target);    
+      DONE;
+    }
   operands[2] = force_reg (<MODE>mode, operands[2]);
 })
 
Index: gcc/testsuite/gcc.target/powerpc/pr83926.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr83926.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr83926.c	(working copy)
@@ -0,0 +1,22 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -mcpu=power8 -mno-fold-gimple" } */
+
+__attribute__ ((altivec(vector__))) long long
+sdiv (__attribute__ ((altivec(vector__))) long long a,
+      __attribute__ ((altivec(vector__))) long long b)
+{
+  return __builtin_vsx_div_2di (a, b);
+}
+__attribute__ ((altivec(vector__))) unsigned long long
+udiv (__attribute__ ((altivec(vector__))) unsigned long long a,
+      __attribute__ ((altivec(vector__))) unsigned long long b)
+{
+  return __builtin_vsx_udiv_2di (a, b);
+}
+__attribute__ ((altivec(vector__))) long long
+smul (__attribute__ ((altivec(vector__))) long long a,
+      __attribute__ ((altivec(vector__))) long long b)
+{
+  return __builtin_vsx_mul_2di (a, b);
+}