I completely forgot ILP32 when I wrote those routines.

gcc/

        * config/loongarch/loongarch.md
        (@stack_protect_combined_set_normal_<mode>): Replace `st.d'
        with `st.<d>', reject stptr.d on LA32 with enabled attribute.
        (@stack_protect_combined_test_internal_<mode>): Replace `ld.d'
        with `ld.<d>', reject ldptr.d on LA32 with enabled attribute.
        (@stack_protect_combined_set_extreme_<mode>): Rename to ...
        (stack_protect_combined_set_extreme): ... here.  Force DImode.
        Add TARGET_ABI_LP64 as the condition.
        (stack_protect_combined_set): Adapt for the change of
        stack_protect_combined_set_extreme.

gcc/testsuite/

        * gcc.target/loongarch/ssp-ilp32.c: New test.
---

Change since v1: disable the alternatives using ldptr/stptr for LA32.

I originally intended to add a new constrant for ldptr/stptr, but to
make the differential really useful we need to tell the compiler some
memory operands are legitimate for atomic operations but not for other
memory operations.  Doing so will need to massively change the
target-independent code.  Considering we need a fix that we can easily
backport to GCC 16, just disable the alternatives ad-hoc.

Bootstrapped and regtested on loongarch64-linux-gnu.  Ok for trunk?

 gcc/config/loongarch/loongarch.md             | 44 ++++++++++++-------
 .../gcc.target/loongarch/ssp-ilp32.c          |  9 ++++
 2 files changed, 37 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/loongarch/ssp-ilp32.c

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index 5c4f8dfb5b5..37ae5a2223e 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -5057,19 +5057,25 @@ (define_insn "@stack_protect_combined_set_normal_<mode>"
   ""
 {
   loongarch_output_asm_load_canary (operands[2], operands[1], NULL_RTX);
-  output_asm_insn (which_alternative ? "stptr.d\t%2,%0" : "st.d\t%2,%0",
+  output_asm_insn (which_alternative ? "stptr.d\t%2,%0"
+                                    : "st.<d>\t%2,%0",
                   operands);
   return "ori\t%2,$r0,0";
 }
   [(set_attr "type" "store")
-   (set_attr "length" "20")])
-
-(define_insn "@stack_protect_combined_set_extreme_<mode>"
-  [(set (match_operand:P 0 "memory_operand" "=m,ZC")
-        (unspec:P [(mem:P (match_operand:P 1 "ssp_operand"))] UNSPEC_SSP))
-   (set (match_scratch:P 2 "=&r,&r") (const_int 0))
-   (set (match_scratch:P 3 "=&r,&r") (const_int 0))]
-  ""
+   (set_attr "length" "20")
+   (set (attr "enabled")
+       (if_then_else
+         (match_test "!which_alternative || TARGET_64BIT")
+         (const_string "yes")
+         (const_string "no")))])
+
+(define_insn "stack_protect_combined_set_extreme"
+  [(set (match_operand:DI 0 "memory_operand" "=m,ZC")
+        (unspec:DI [(mem:DI (match_operand:DI 1 "ssp_operand"))] UNSPEC_SSP))
+   (set (match_scratch:DI 2 "=&r,&r") (const_int 0))
+   (set (match_scratch:DI 3 "=&r,&r") (const_int 0))]
+  "TARGET_ABI_LP64"
 {
   loongarch_output_asm_load_canary (operands[2], operands[1], operands[3]);
   output_asm_insn (which_alternative ? "stptr.d\t%2,%0" : "st.d\t%2,%0",
@@ -5092,12 +5098,17 @@ (define_insn 
"@stack_protect_combined_test_internal_<mode>"
   rtx t = (which_alternative >= 2 ? operands[0] : NULL_RTX);
   loongarch_output_asm_load_canary (operands[3], operands[2], t);
   output_asm_insn ((which_alternative & 1) ? "ldptr.d\t%0,%1"
-                                          : "ld.d\t%0,%1",
+                                          : "ld.<d>\t%0,%1",
                   operands);
   return "xor\t%0,%0,%3\n\tori\t%3,$r0,0";
 }
   [(set_attr "type" "load,load,load,load")
-   (set_attr "length" "24,24,36,36")])
+   (set_attr "length" "24,24,36,36")
+   (set (attr "enabled")
+       (if_then_else
+         (match_test "!(which_alternative & 1) || TARGET_64BIT")
+         (const_string "yes")
+         (const_string "no")))])
 
 (define_expand "stack_protect_combined_set"
   [(match_operand 0 "memory_operand")
@@ -5105,11 +5116,12 @@ (define_expand "stack_protect_combined_set"
   ""
 {
   rtx canary = XEXP (operands[1], 0);
-  auto fn = (ssp_normal_operand (canary, VOIDmode)
-            ? gen_stack_protect_combined_set_normal
-            : gen_stack_protect_combined_set_extreme);
-
-  emit_insn (fn (Pmode, operands[0], canary));
+  if (ssp_normal_operand (canary, VOIDmode))
+    emit_insn (gen_stack_protect_combined_set_normal (Pmode, operands[0],
+                                                     canary));
+  else
+    emit_insn (gen_stack_protect_combined_set_extreme (operands[0],
+                                                      canary));
   DONE;
 })
 
diff --git a/gcc/testsuite/gcc.target/loongarch/ssp-ilp32.c 
b/gcc/testsuite/gcc.target/loongarch/ssp-ilp32.c
new file mode 100644
index 00000000000..1bdb61bfc72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/ssp-ilp32.c
@@ -0,0 +1,9 @@
+/* { dg-options "-march=la32v1.0 -mabi=ilp32s -fstack-protector-strong" } */
+/* { dg-final { scan-assembler-not "ld\\\.d" } } */
+/* { dg-final { scan-assembler-not "st\\\.d" } } */
+
+void test()
+{
+       int x;
+       asm("":"+m"(x));
+}
-- 
2.54.0

Reply via email to