The following patch fixes a semi-latent bug for the HTM pattern used with the __builtin_ttest() builtin. This is supposed to expand to a tabortwci. instruction which sets cr0 and then some code that copies the cr0 value into a gpr and then shifts and masks it into the lowest 2 bits in the gpr.
With newish -mcpu targets, we generate a "mfocrf rX,128" to copy the cr0 value into bits 32-35 of the gpr. However, in some cases, we will instead generate a "mfcr rX" instruction, which copies all 8 CR fields into the gpr, with cr0 again being in bits 32-35. The difference is that the mfocrf instruction seems to duplicate the 4-bit CR field in the gpr, so bits 36-39 are a duplicate of bits 32-35. The error in the ttest pattern is that we only shift the value down 24 bits. This "works" when a mfocrf copied the cr0 into the rgeister due the duplicated CR field, but is wrong when a mfcr instruction is used. The following passed bootstrap and regtesting on powerpc64-linux. Ok for trunk? Is this also ok for the 4.9 and 4.8 branches once my bootstraps and regtesting is done there? Peter gcc/ * config/rs6000/htm.md (ttest): Use correct shift value to get CR0. gcc/testsuite/ * gcc.target/powerpc/htm-ttest.c: New test. Index: gcc/config/rs6000/htm.md =================================================================== --- gcc/config/rs6000/htm.md (revision 210518) +++ gcc/config/rs6000/htm.md (working copy) @@ -179,7 +179,7 @@ (define_expand "ttest" (const_int 0)] UNSPECV_HTM_TABORTWCI)) (set (subreg:CC (match_dup 2) 0) (match_dup 1)) - (set (match_dup 3) (lshiftrt:SI (match_dup 2) (const_int 24))) + (set (match_dup 3) (lshiftrt:SI (match_dup 2) (const_int 28))) (parallel [(set (match_operand:SI 0 "int_reg_operand" "") (and:SI (match_dup 3) (const_int 15))) (clobber (scratch:CC))])] Index: gcc/testsuite/gcc.target/powerpc/htm-ttest.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/htm-ttest.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/htm-ttest.c (working copy) @@ -0,0 +1,14 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_htm_ok } */ +/* { dg-options "-O2 -mhtm" } */ + +/* { dg-final { scan-assembler "rlwinm r?\[0-9\]+,r?\[0-9\]+,3,30,31" { target { ilp32 } } } } */ +/* { dg-final { scan-assembler "rldicl r?\[0-9\]+,r?\[0-9\]+,35,62" { target { lp64 } } } } */ + +#include <htmintrin.h> +long +ttest (void) +{ + return _HTM_STATE(__builtin_ttest()); +}