llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.76k stars 11.89k forks source link

failure to convert FP addition loop into a constant #28273

Open rotateright opened 8 years ago

rotateright commented 8 years ago
Bugzilla Link 27899
Version trunk
OS All
CC @atrick,@delena,@hfinkel,@jmolloy,@RKSimon,@sanjoy

Extended Description

If we continue on the path from the realistic (bug 27881, bug 27894) to the absurd, I think we end here. :)

float OneMeelion() { float sum = 0.0f; for (int i = 0; i < 1000; i++) sum += 1000.0f;

return sum; }

We don't need fast-math to know this answer.

$ ./clang -O2 OneMeelion.c -S -o - ... xorps %xmm0, %xmm0 movl $1000, %eax ## imm = 0x3E8 movss LCPI0_0(%rip), %xmm1 ## xmm1 = mem[0],zero,zero,zero .p2align 4, 0x90 LBB0_1: ## %for.body

=>This Inner Loop Header: Depth=1

addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addss   %xmm1, %xmm0
addl    $-10, %eax
jne LBB0_1

Surprisingly, this didn't vectorize!

That's because "-Rpass-analysis=loop-vectorize": remark: loop not vectorized: cannot prove it is safe to reorder floating-point operations

rotateright commented 8 years ago

Are we guaranteed in this case that rounding wouldn't change the result?

That's a good question. I mentioned a similar potential difference for the fast-math case in bug 27894, comment 4.

I don't think we currently support any rounding-mode changes, although I know there have been proposals to fix that in the last ~year.

So for now, I think we'd just compute the answer for the default rounding-mode and note that this transform should be made rounding-mode aware when that infrastructure arrives?

Also, I haven't tried this patch yet: http://reviews.llvm.org/D20695

...does SCEV FP infrastructure need to be rounding-mode aware? (cc Elena).

jmolloy commented 8 years ago

If you modify your testcase:

float TenMeelion?() { float sum = 0.0f; for (int i = 0; i < 10000; i++) sum += 1000.0f;

return sum; }

then "sum" should be 10000000.0f (and it is). But this is now off the end of the mantissa (2**23) and we're no longer guaranteed that every value is representable. Are we guaranteed in this case that rounding wouldn't change the result?