<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - float instructions should only be lowered to NEON if precision constraints permit"
   href="http://llvm.org/bugs/show_bug.cgi?id=16274">16274</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>float instructions should only be lowered to NEON if precision constraints permit
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Backend: ARM
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>grosser@fim.uni-passau.de
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=10653" name="attach_10653" title="Test file attached">attachment 10653</a> <a href="attachment.cgi?id=10653&action=edit" title="Test file attached">[details]</a></span>
Test file attached

On ARM it is difficult to generate optimal code that matches certain floating
point precision requirements. The only way that currently exist is to
explicitly alter the feature flags of the CPU that we target. This currently
causes problems, such that it is e.g. not possible to take advantage of NEON
for integer instructions while at the same time NEON is avoided for vector
floating point operations.

The following test cases illustrate how I expect llc to behave:

; RUN: llc -march=arm -mattr=+vfp3,+neon,+neonfp < %s | FileCheck %s
; RUN: llc -march=arm -mattr=+vfp3,+neon,-neonfp
-enable-flush-denormals-fp-math < %s | FileCheck %s -check-prefix=ALLOW-FLUSH

; fooP() performs a vector floating point multiplication with full precision
; requirement. Even if some piece of hardware supports NEON (modeled with
; -mattr=+neon), NEON should not be used to implement this function as NEON
; does not comply to the full precision requirements (NEON rounds denormals
; to zero)
;
; However, if the user specifies flushing denormals to zero is legal, we should
; obviously use NEON.
define <4 x float> @fooP(<4 x float> %A, <4 x float> %B)
{
        %C = fmul <4 x float> %A, %B
; CHECK: fooP
; CHECK: vmul.f32       s
; CHECK: vmul.f32       s
; CHECK: vmul.f32       s
; CHECK: vmul.f32       s

; CHECK-ALLOW-FLUSH: fooP
; CHECK-ALLOW-FLUSH: vmul.f32   q
        ret <4 x float> %C
}

; fooR() performs a vector floating point multiplication with relaxed precision
; requirements. In case the precision loss introduced by neon is acceptable
; we should generate NEON instructions
;
; Relaxed precision requirements can be specified by using the fast-math flag
; fast or by introducing a specific allow-flush-denormals flag in LLVM-IR.
define <4 x float> @fooR(<4 x float> %A, <4 x float> %B)
{
        %C = fmul fast <4 x float> %A, %B

; We may decide to not implement this immediately as making decissions based on
; the floating point flags may require costum lowering of instructions.
; CHECK: fooR
; CHECK: vmul.f32       q

; CHECK-ALLOW-FLUSH: fooR
; CHECK-ALLOW-FLUSH: vmul.f32   q
        ret <4 x float> %C
}

; fooS() perform a scalar floating point multiplication.
;
; On some ARM devices scalar floating point operations are faster when executed
; with NEON instructions. This is modeled by the '+neonfp' feature flag.
;
; Independently on which features the device supports (and which features are
; fast on a device) we should use NEON only if it matches the precision
; requirements of the target as provided by an -enable-flush-denormals-fp-math
; option. (The default for this option may differ on darwin and non-darwin
; systems).
define float @fooS(float %A, float %B)
{
        %C = fmul fast float %A, %B

; CHECK: fooS
; CHECK: vmul.f32       s
; CHECK: vmul.f32       s
; CHECK: vmul.f32       s
; CHECK: vmul.f32       s

; CHECK-ALLOW-FLUSH: fooS
; CHECK-ALLOW-FLUSH: vmul.f32   q
        ret float %C
}

; bar() performs a vector integer multiplication. On an ARM NEON device, this
; code should always be execute as vector code, as floating point precision
; requirements do not apply.
define <4 x i32> @bar(<4 x i32> %A, <4 x i32> %B)
{
        %C = mul <4 x i32> %A, %B
; CHECK: bar
; CHECK: vmul.i32       q

; CHECK-ALLOW-FLUSH: bar
; CHECK-ALLOW-FLUSH: vmul.i32   q
        ret <4 x i32> %C
}</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>