bitfield_store_spill.c (2733B)
1 /* Bitfield store under register pressure. A 2-bit bitfield assignment is a 2 * read-modify-write that must keep the destination word's address live while 3 * the new field value is materialized. With enough live struct pointers the 4 * store's pointer spills and is reloaded into a scratch register; the value 5 * must NOT be materialized into that same scratch register. The -O1 native 6 * emitter once placed the value into the address's scratch, nulling the 7 * pointer (a SIGSEGV in optimized SQLite). Each f0=i%4, f1 must stay intact; 8 * sum of f0 over 24 structs = (0+1+2+3)*6 = 36. */ 9 struct S { long pad[3]; unsigned f0 : 2; unsigned f1 : 30; }; 10 11 int test_main(void) { 12 struct S s[24]; 13 for (int i = 0; i < 24; i++) { s[i].f0 = 3; s[i].f1 = (unsigned)(0x100 + i); } 14 struct S *p0 = &s[0],*p1 = &s[1],*p2 = &s[2],*p3 = &s[3],*p4 = &s[4],*p5 = &s[5],*p6 = &s[6],*p7 = &s[7],*p8 = &s[8],*p9 = &s[9],*p10 = &s[10],*p11 = &s[11],*p12 = &s[12],*p13 = &s[13],*p14 = &s[14],*p15 = &s[15],*p16 = &s[16],*p17 = &s[17],*p18 = &s[18],*p19 = &s[19],*p20 = &s[20],*p21 = &s[21],*p22 = &s[22],*p23 = &s[23]; 15 p0->f0 = 0; p1->f0 = 1; p2->f0 = 2; p3->f0 = 3; p4->f0 = 0; p5->f0 = 1; p6->f0 = 2; p7->f0 = 3; p8->f0 = 0; p9->f0 = 1; p10->f0 = 2; p11->f0 = 3; p12->f0 = 0; p13->f0 = 1; p14->f0 = 2; p15->f0 = 3; p16->f0 = 0; p17->f0 = 1; p18->f0 = 2; p19->f0 = 3; p20->f0 = 0; p21->f0 = 1; p22->f0 = 2; p23->f0 = 3; 16 int sum = (int)p0->f0 + (int)p1->f0 + (int)p2->f0 + (int)p3->f0 + (int)p4->f0 + (int)p5->f0 + (int)p6->f0 + (int)p7->f0 + (int)p8->f0 + (int)p9->f0 + (int)p10->f0 + (int)p11->f0 + (int)p12->f0 + (int)p13->f0 + (int)p14->f0 + (int)p15->f0 + (int)p16->f0 + (int)p17->f0 + (int)p18->f0 + (int)p19->f0 + (int)p20->f0 + (int)p21->f0 + (int)p22->f0 + (int)p23->f0; 17 int f1ok = (s[0].f1 == (unsigned)(0x100 + 0)) + (s[1].f1 == (unsigned)(0x100 + 1)) + (s[2].f1 == (unsigned)(0x100 + 2)) + (s[3].f1 == (unsigned)(0x100 + 3)) + (s[4].f1 == (unsigned)(0x100 + 4)) + (s[5].f1 == (unsigned)(0x100 + 5)) + (s[6].f1 == (unsigned)(0x100 + 6)) + (s[7].f1 == (unsigned)(0x100 + 7)) + (s[8].f1 == (unsigned)(0x100 + 8)) + (s[9].f1 == (unsigned)(0x100 + 9)) + (s[10].f1 == (unsigned)(0x100 + 10)) + (s[11].f1 == (unsigned)(0x100 + 11)) + (s[12].f1 == (unsigned)(0x100 + 12)) + (s[13].f1 == (unsigned)(0x100 + 13)) + (s[14].f1 == (unsigned)(0x100 + 14)) + (s[15].f1 == (unsigned)(0x100 + 15)) + (s[16].f1 == (unsigned)(0x100 + 16)) + (s[17].f1 == (unsigned)(0x100 + 17)) + (s[18].f1 == (unsigned)(0x100 + 18)) + (s[19].f1 == (unsigned)(0x100 + 19)) + (s[20].f1 == (unsigned)(0x100 + 20)) + (s[21].f1 == (unsigned)(0x100 + 21)) + (s[22].f1 == (unsigned)(0x100 + 22)) + (s[23].f1 == (unsigned)(0x100 + 23)); 18 return sum + (f1ok == 24 ? 0 : 100); 19 }