PR87870 shows a problem loading simple constant values into TImode variables. This is a regression ever since VSX was added and we started using the vsx_mov<mode>_64bit pattern. We still get the correct code on trunk if we compile with -mno-vsx, since we fall back to using the older mov<mode>_ppc64 move pattern, which has an alternative "r" <- "n".
Our current vsx_mov<mode>_64bit pattern currently has two alternatives for loading constants into GPRs, one using "*r" <- "jwM" and "??r" <- "W". These look redundant to me, since "W" contains support for both all-zero constants (ie, "j") and all-one constants (ie, wM) as well as a few more. My patch below consolidates them both and uses a new mode iterator that uses "W" for the vector modes and "n" for TImode like mov<mode>_ppc64 used. I'll note I didn't change the vsx_mov<mode>_32bit pattern, since TImode isn't supported with -m32. However, if you want, I could remove the redundant "*r" <- "jwM" alternative there too? This passes bootstrap and regtesting with no regressions. Ok for trunk? Peter gcc/ PR target/87870 * config/rs6000/vsx.md (nW): New mode iterator. (vsx_mov<mode>_64bit): Use it. Remove redundant GPR 0/-1 alternative. gcc/testsuite/ PR target/87870 * gcc.target/powerpc/pr87870.c: New test. Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 265971) +++ gcc/config/rs6000/vsx.md (working copy) @@ -183,6 +183,18 @@ (define_mode_attr ??r [(V16QI "??r") (TF "??r") (TI "r")]) +;; A mode attribute used for 128-bit constant values. +(define_mode_attr nW [(V16QI "W") + (V8HI "W") + (V4SI "W") + (V4SF "W") + (V2DI "W") + (V2DF "W") + (V1TI "W") + (KF "W") + (TF "W") + (TI "n")]) + ;; Same size integer type for floating point data (define_mode_attr VSi [(V4SF "v4si") (V2DF "v2di") @@ -1193,17 +1205,17 @@ (define_insn_and_split "*xxspltib_<mode> ;; VSX store VSX load VSX move VSX->GPR GPR->VSX LQ (GPR) ;; STQ (GPR) GPR load GPR store GPR move XXSPLTIB VSPLTISW -;; VSX 0/-1 GPR 0/-1 VMX const GPR const LVX (VMX) STVX (VMX) +;; VSX 0/-1 VMX const GPR const LVX (VMX) STVX (VMX) (define_insn "vsx_mov<mode>_64bit" [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=ZwO, <VSa>, <VSa>, r, we, ?wQ, ?&r, ??r, ??Y, <??r>, wo, v, - ?<VSa>, *r, v, ??r, wZ, v") + ?<VSa>, v, <??r>, wZ, v") (match_operand:VSX_M 1 "input_operand" "<VSa>, ZwO, <VSa>, we, r, r, wQ, Y, r, r, wE, jwM, - ?jwM, jwM, W, W, v, wZ"))] + ?jwM, W, <nW>, v, wZ"))] "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode) && (register_operand (operands[0], <MODE>mode) @@ -1214,12 +1226,12 @@ (define_insn "vsx_mov<mode>_64bit" [(set_attr "type" "vecstore, vecload, vecsimple, mffgpr, mftgpr, load, store, load, store, *, vecsimple, vecsimple, - vecsimple, *, *, *, vecstore, vecload") + vecsimple, *, *, vecstore, vecload") (set_attr "length" "4, 4, 4, 8, 4, 8, 8, 8, 8, 8, 4, 4, - 4, 8, 20, 20, 4, 4")]) + 4, 20, 20, 4, 4")]) ;; VSX store VSX load VSX move GPR load GPR store GPR move ;; XXSPLTIB VSPLTISW VSX 0/-1 GPR 0/-1 VMX const GPR const Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 265971) +++ gcc/config/rs6000/vsx.md (working copy) @@ -183,6 +183,18 @@ (define_mode_attr ??r [(V16QI "??r") (TF "??r") (TI "r")]) +;; A mode attribute used for 128-bit constant values. +(define_mode_attr nW [(V16QI "W") + (V8HI "W") + (V4SI "W") + (V4SF "W") + (V2DI "W") + (V2DF "W") + (V1TI "W") + (KF "W") + (TF "W") + (TI "n")]) + ;; Same size integer type for floating point data (define_mode_attr VSi [(V4SF "v4si") (V2DF "v2di") @@ -1193,17 +1205,17 @@ (define_insn_and_split "*xxspltib_<mode> ;; VSX store VSX load VSX move VSX->GPR GPR->VSX LQ (GPR) ;; STQ (GPR) GPR load GPR store GPR move XXSPLTIB VSPLTISW -;; VSX 0/-1 GPR 0/-1 VMX const GPR const LVX (VMX) STVX (VMX) +;; VSX 0/-1 VMX const GPR const LVX (VMX) STVX (VMX) (define_insn "vsx_mov<mode>_64bit" [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=ZwO, <VSa>, <VSa>, r, we, ?wQ, ?&r, ??r, ??Y, <??r>, wo, v, - ?<VSa>, *r, v, ??r, wZ, v") + ?<VSa>, v, <??r>, wZ, v") (match_operand:VSX_M 1 "input_operand" "<VSa>, ZwO, <VSa>, we, r, r, wQ, Y, r, r, wE, jwM, - ?jwM, jwM, W, W, v, wZ"))] + ?jwM, W, <nW>, v, wZ"))] "TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode) && (register_operand (operands[0], <MODE>mode) @@ -1214,12 +1226,12 @@ (define_insn "vsx_mov<mode>_64bit" [(set_attr "type" "vecstore, vecload, vecsimple, mffgpr, mftgpr, load, store, load, store, *, vecsimple, vecsimple, - vecsimple, *, *, *, vecstore, vecload") + vecsimple, *, *, vecstore, vecload") (set_attr "length" "4, 4, 4, 8, 4, 8, 8, 8, 8, 8, 4, 4, - 4, 8, 20, 20, 4, 4")]) + 4, 20, 20, 4, 4")]) ;; VSX store VSX load VSX move GPR load GPR store GPR move ;; XXSPLTIB VSPLTISW VSX 0/-1 GPR 0/-1 VMX const GPR const Index: gcc/testsuite/gcc.target/powerpc/pr87870.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr87870.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/pr87870.c (working copy) @@ -0,0 +1,28 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-options "-O2" } */ + +__int128 +test0 (void) +{ + return 0; +} + +__int128 +test1 (void) +{ + return 1; +} + +__int128 +test2 (void) +{ + return -1; +} + +__int128 +test3 (void) +{ + return ((__int128)0xdeadbeefcafebabe << 64) | 0xfacefeedbaaaaaad; +} + +/* { dg-final { scan-assembler-not {\mld\M} } } */