1 /* https://bugs.kde.org/show_bug.cgi?id=308627 */
2 
3 #include "../../memcheck.h"
4 
5 #include <stdio.h>
6 
7 typedef unsigned long ULong;
8 
9 typedef struct {
10    ULong w64[2];  /* Note: little-endian */
11 } V128;
12 
getMSBs16x8(V128 v)13 static int getMSBs16x8(V128 v)
14 {
15    int result;
16    __asm__("movups %1,%%xmm6\n"
17            "\tpmovmskb %%xmm6,%0\n"
18            : "=r" (result) : "m" (v) : "xmm6");
19    return result;
20 }
21 
22 /* Set the V bits on the data at "addr".  Note the convention: A zero
23    bit means "defined"; 1 means "undefined". */
set_vbits(V128 * addr,V128 vbits)24 static void set_vbits(V128 *addr, V128 vbits)
25 {
26    int i;
27    for (i=0 ; i<2 ; ++i) {
28       (void)VALGRIND_SET_VBITS(&addr->w64[i], &vbits.w64[i], sizeof(vbits.w64[i]));
29    }
30 }
31 
print(V128 vbits,V128 val,int bit,int result)32 static void print(V128 vbits, V128 val, int bit, int result)
33 {
34    printf("vbits=0x%016lx%016lx val=0x%016lx%016lx bit=%d result=%d\n",
35           vbits.w64[1], vbits.w64[0], val.w64[1], val.w64[0],
36           bit, result);
37 }
38 
39 /* Use a value that we know is invalid. */
use(int index,int invalid)40 static void use(int index, int invalid)
41 {
42    /* Convince GCC it does not know what is in "invalid" so it cannot
43       possibly optimize away the conditional branch below. */
44    __asm__ ("" : "=r" (invalid) : "0" (invalid));
45 
46    /* Create a conditional branch on which our output depends, so that
47       memcheck cannot possibly optimize it away, either. */
48    fprintf(stderr, "%d: Invalid value is %s\n",
49            index, invalid ? "true" : "false");
50 }
51 
doit(ULong vbits_hi,ULong vbits_lo,ULong val_hi,ULong val_lo)52 static void doit(ULong vbits_hi, ULong vbits_lo, ULong val_hi, ULong val_lo)
53 {
54    V128 vbits = { { vbits_lo, vbits_hi } };
55    V128 val = { { val_lo, val_hi } };
56 
57    /* Since we are about to mark "val" partially undefined, make a
58       copy that we can use without generating a memcheck warning. */
59    V128 val_copy = val;
60 
61    set_vbits(&val, vbits);
62 
63    int result = getMSBs16x8(val);
64 
65    int vbits_mask = getMSBs16x8(vbits);
66 
67    int bit = 0; ULong mask = (1UL << bit);
68    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
69    else use(bit, result & mask);
70 
71    bit = 1; mask = (1UL << bit);
72    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
73    else use(bit, result & mask);
74 
75    bit = 2; mask = (1UL << bit);
76    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
77    else use(bit, result & mask);
78 
79    bit = 3; mask = (1UL << bit);
80    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
81    else use(bit, result & mask);
82 
83    bit = 4; mask = (1UL << bit);
84    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
85    else use(bit, result & mask);
86 
87    bit = 5; mask = (1UL << bit);
88    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
89    else use(bit, result & mask);
90 
91    bit = 6 ; mask = (1UL << bit);
92    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
93    else use(bit, result & mask);
94 
95    bit = 7 ; mask = (1UL << bit);
96    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
97    else use(bit, result & mask);
98 
99    bit = 8 ; mask = (1UL << bit);
100    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
101    else use(bit, result & mask);
102 
103    bit = 9 ; mask = (1UL << bit);
104    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
105    else use(bit, result & mask);
106 
107    bit = 10 ; mask = (1UL << bit);
108    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
109    else use(bit, result & mask);
110 
111    bit = 11 ; mask = (1UL << bit);
112    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
113    else use(bit, result & mask);
114 
115    bit = 12 ; mask = (1UL << bit);
116    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
117    else use(bit, result & mask);
118 
119    bit = 13 ; mask = (1UL << bit);
120    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
121    else use(bit, result & mask);
122 
123    bit = 14 ; mask = (1UL << bit);
124    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
125    else use(bit, result & mask);
126 
127    bit = 15 ; mask = (1UL << bit);
128    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
129    else use(bit, result & mask);
130 }
131 
main(int argc,char * argv[])132 int main(int argc, char *argv[])
133 {
134    doit(0x0000000000000000, 0x0000000000000000,
135         0x0000000000000000, 0x0000000000000000);
136 
137    doit(0x0707070707070707, 0x0707070707070707,
138         0x0000000000000000, 0x0000000000000000);
139 
140    doit(0x8080808080808080, 0x8080808080808080,
141         0x0000000000000000, 0x0000000000000000);
142 
143    doit(0x13579BDF02468ACE, 0xFEDCBA9876543210,
144         0xFEEDFACEDEADBEEF, 0xFEE1DEADDABBAD00);
145 
146    return 0;
147 }
148