[PATCH] D30542: [ARM] fpscr read/write intrinsics not aware of each other.

Ranjeet Singh via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 2 10:16:52 PST 2017


rs created this revision.
Herald added a subscriber: aemerson.

  The intrinsics __builtin_arm_get_fpscr and __builtin_arm_set_fpscr read
  from and write to the fpscr (Floating-Point Status and Control Register)
  register.
  
  A translation fault occurs if there is a read then write then read from
  this register:
  
  void foo(int *p) { p[0] = __builtin_arm_get_fpscr();
  __builtin_arm_set_fpscr(1); p[1] = __builtin_arm_get_fpscr(); }
  
  The generated code for the above example only has one read and one write
  the second read is common sub-expression eliminated into the first read.
  This is obviously wrong. I think the reason this is happening is due to
  the intrinsic definition in IntrinsicsARM.td for arm_get_fpscr which has
  IntrNoMem:
  
  def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">,
  Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
  
  the definition for IntrNoMem is:
  
  // IntrNoMem - The intrinsic does not access memory or have any other
  // side effects.  It may be CSE'd deleted if dead, etc.
  def IntrNoMem : IntrinsicProperty;
  
  The problem is that LLVM doesn't realize it's reading the register that
  __builtin_arm_set_fpscr wrote. So a potential fix for this problem could
  be to treat a read of fpscr as a memory access the same way as a write
  is treated as a memory access.


https://reviews.llvm.org/D30542

Files:
  include/llvm/IR/IntrinsicsARM.td
  test/CodeGen/ARM/fpscr-intrinsics.ll


Index: test/CodeGen/ARM/fpscr-intrinsics.ll
===================================================================
--- /dev/null
+++ test/CodeGen/ARM/fpscr-intrinsics.ll
@@ -0,0 +1,22 @@
+; RUN: llc < %s -mtriple=armv7-eabi -mcpu=cortex-a8 | FileCheck %s
+
+; Function Attrs: nounwind
+define void @fn1(i32* nocapture %p) local_unnamed_addr #0 {
+entry:
+  ; CHECK: vmrs r{{[0-9]+}}, fpscr
+  %0 = tail call i32 @llvm.arm.get.fpscr()
+  store i32 %0, i32* %p, align 4
+  ; CHECK: vmsr fpscr, r{{[0-9]+}}
+  tail call void @llvm.arm.set.fpscr(i32 1)
+  ; CHECK: vmrs r{{[0-9]+}}, fpscr
+  %1 = tail call i32 @llvm.arm.get.fpscr()
+  %arrayidx1 = getelementptr inbounds i32, i32* %p, i32 1
+  store i32 %1, i32* %arrayidx1, align 4
+  ret void
+}
+
+; Function Attrs: nounwind readonly
+declare i32 @llvm.arm.get.fpscr() #1
+
+; Function Attrs: nounwind writeonly
+declare void @llvm.arm.set.fpscr(i32) #2
Index: include/llvm/IR/IntrinsicsARM.td
===================================================================
--- include/llvm/IR/IntrinsicsARM.td
+++ include/llvm/IR/IntrinsicsARM.td
@@ -67,7 +67,7 @@
 // VFP
 
 def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">,
-                       Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
+                       Intrinsic<[llvm_i32_ty], [], []>;
 def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">,
                        Intrinsic<[], [llvm_i32_ty], []>;
 def int_arm_vcvtr     : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty],


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30542.90353.patch
Type: text/x-patch
Size: 1494 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170302/115972e1/attachment.bin>


More information about the llvm-commits mailing list