4 ms·
> The way the x87 FP stack works is a bit weird, and these days it’s better to do floating-point arithmetic using xmm registers x87 allows to do calculations i
by wmu 10y ago
> The way the x87 FP stack works is a bit weird, and these days it’s better to do floating-point arithmetic using xmm registers
x87 allows to do calculations in extended precision, i.e. word width is 80 bits. SSE is limited to double precision (64-bit words). Also FPU has some advanced math instructions, like sin, cos, tan, exp, etc., and these operations will be available in AVX512F.
- wolf550e 10y agoHave fun debugging arithmetic difference resulting from spilling an intermediate result to memory and rounding to 64bit value vs. not spilling and keeping the intermediate value as 80 bits.
- qb45 10y agoFST/FLD can store/load full 80 bits if you need such precision. No problem whatsoever.
- wolf550e 10y agoI've never seen anyone store 10 byte IEEE-754 values in memory. People store doubles, and people get upset when compiler optimizations (like when to spill from registers to memory and whether to use one or two instructions for multiply-and-add) change not just the performance but also the result of computations.
- qb45 10y ago> I've never seen anyone store 10 byte IEEE-754 values in memory. But you can, if you are after precision as the OP apparently was. I'm not sure what this c-word is doing in your post, I thought we were talking assembly, but as far as c-things go, at least gcc and clang represent long double as 80b extended precision on x86. So, for example, compiling this beauty (which is too large for x87 stack): long double a[64], b[64], c[64], d[64]; // load a,b,c,d from somewhere long double x = ((((((((a[0]+a[1])+(a[2]+a[3]))+((a[4]+a[5])+(a[6]+a[7]))) +(((a[8]+a[9])+(a[10]+a[11]))+((a[12]+a[13])+(a[14]+a[15])))) +((((a[16]+a[17])+(a[18]+a[19]))+((a[20]+a[21])+(a[22]+a[23]))) +(((a[24]+a[25])+(a[26]+a[27]))+((a[28]+a[29])+(a[30]+a[31]))))) +(((((a[32]+a[33])+(a[34]+a[35]))+((a[36]+a[37])+(a[38]+a[39]))) +(((a[40]+a[41])+(a[42]+a[43]))+((a[44]+a[45])+(a[46]+a[47])))) +((((a[48]+a[49])+(a[50]+a[51]))+((a[52]+a[53])+(a[54]+a[55]))) +(((a[56]+a[57])+(a[58]+a[59]))+((a[60]+a[61])+(a[62]+a[63])))))) +((((((b[0]+b[1])+(b[2]+b[3]))+((b[4]+b[5])+(b[6]+b[7]))) +(((b[8]+b[9])+(b[10]+b[11]))+((b[12]+b[13])+(b[14]+b[15])))) +((((b[16]+b[17])+(b[18]+b[19]))+((b[20]+b[21])+(b[22]+b[23]))) +(((b[24]+b[25])+(b[26]+b[27]))+((b[28]+b[29])+(b[30]+b[31]))))) +(((((b[32]+b[33])+(b[34]+b[35]))+((b[36]+b[37])+(b[38]+b[39]))) +(((b[40]+b[41])+(b[42]+b[43]))+((b[44]+b[45])+(b[46]+b[47])))) +((((b[48]+b[49])+(b[50]+b[51]))+((b[52]+b[53])+(b[54]+b[55]))) +(((b[56]+b[57])+(b[58]+b[59]))+((b[60]+b[61])+(b[62]+b[63]))))))) +(((((((c[0]+c[1])+(c[2]+c[3]))+((c[4]+c[5])+(c[6]+c[7]))) +(((c[8]+c[9])+(c[10]+c[11]))+((c[12]+c[13])+(c[14]+c[15])))) +((((c[16]+c[17])+(c[18]+c[19]))+((c[20]+c[21])+(c[22]+c[23]))) +(((c[24]+c[25])+(c[26]+c[27]))+((c[28]+c[29])+(c[30]+c[31]))))) +(((((c[32]+c[33])+(c[34]+c[35]))+((c[36]+c[37])+(c[38]+c[39]))) +(((c[40]+c[41])+(c[42]+c[43]))+((c[44]+c[45])+(c[46]+c[47])))) +((((c[48]+c[49])+(c[50]+c[51]))+((c[52]+c[53])+(c[54]+c[55]))) +(((c[56]+c[57])+(c[58]+c[59]))+((c[60]+c[61])+(c[62]+c[63])))))) +((((((d[0]+d[1])+(d[2]+d[3]))+((d[4]+d[5])+(d[6]+d[7]))) +(((d[8]+d[9])+(d[10]+d[11]))+((d[12]+d[13])+(d[14]+d[15])))) +((((d[16]+d[17])+(d[18]+d[19]))+((d[20]+d[21])+(d[22]+d[23]))) +(((d[24]+d[25])+(d[26]+d[27]))+((d[28]+d[29])+(d[30]+d[31]))))) +(((((d[32]+d[33])+(d[34]+d[35]))+((d[36]+d[37])+(d[38]+d[39]))) +(((d[40]+d[41])+(d[42]+d[43]))+((d[44]+d[45])+(d[46]+d[47])))) +((((d[48]+d[49])+(d[50]+d[51]))+((d[52]+d[53])+(d[54]+d[55]))) +(((d[56]+d[57])+(d[58]+d[59]))+((d[60]+d[61])+(d[62]+d[63])))))))) ; produces only 80b spills (fstpt in GNU syntax): $ objdump -d fpmonster |grep fst 400457: db 7c 1c 10 fstpt 0x10(%rsp,%rbx,1) 400462: db bc 1c 10 04 00 00 fstpt 0x410(%rsp,%rbx,1) 400470: db bc 1c 10 08 00 00 fstpt 0x810(%rsp,%rbx,1) 40047e: db bc 1c 10 0c 00 00 fstpt 0xc10(%rsp,%rbx,1) 400b47: db 7c 24 10 fstpt 0x10(%rsp) 400d91: db 3c 24 fstpt (%rsp) Clearly, extended precision can be done right both in C and raw assembly. > People store doubles, and people get upset That's their fault :) and another story altogether. For reproducible low precision, indeed SSE is the way to go.
- deleted 10y ago[deleted]