[cfe-commits] r149086 - in /cfe/trunk: include/clang/Basic/TargetInfo.h lib/Basic/Targets.cpp lib/CodeGen/CGBuiltin.cpp test/CodeGen/builtin-count-zeros.c

Bob Wilson bob.wilson at apple.com
Thu Jan 26 14:14:27 PST 2012


Author: bwilson
Date: Thu Jan 26 16:14:27 2012
New Revision: 149086

URL: http://llvm.org/viewvc/llvm-project?rev=149086&view=rev
Log:
Make clz/ctz builtins defined for zero on ARM targets.  rdar://10732455

ARM supports clz and ctz directly and both operations have well-defined
results for zero.  There is no disadvantage in performance to using the
defined-at-zero versions of llvm.ctlz/cttz intrinsics.  We're running into
ARM-specific code written with the assumption that __builtin_clz(0) == 32,
even though that value is technically undefined.  The code is failing now
because of llvm optimizations that are taking advantage of the undef
behavior (specifically svn r147255).  There's nothing wrong with that
optimization on x86 where any incorrect assumptions about __builtin_clz(0)
will quickly be exposed.  For ARM, though, optimizations based on that undef
behavior are likely to cause subtle bugs.  Other targets with defined-at-zero
clz/ctz support may want to override the default behavior as well.

Modified:
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/test/CodeGen/builtin-count-zeros.c

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=149086&r1=149085&r2=149086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Thu Jan 26 16:14:27 2012
@@ -357,6 +357,13 @@
   virtual void getTargetBuiltins(const Builtin::Info *&Records,
                                  unsigned &NumRecords) const = 0;
 
+  /// isCLZForZeroUndef - The __builtin_clz* and __builtin_ctz* built-in
+  /// functions are specified to have undefined results for zero inputs, but
+  /// on targets that support these operations in a way that provides
+  /// well-defined results for zero without loss of performance, it is a good
+  /// idea to avoid optimizing based on that undef behavior.
+  virtual bool isCLZForZeroUndef() const { return true; }
+
   /// getVAListDeclaration - Return the declaration to use for
   /// __builtin_va_list, which is target-specific.
   virtual const char *getVAListDeclaration() const = 0;

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=149086&r1=149085&r2=149086&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Thu Jan 26 16:14:27 2012
@@ -2778,6 +2778,7 @@
     Records = BuiltinInfo;
     NumRecords = clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin;
   }
+  virtual bool isCLZForZeroUndef() const { return false; }
   virtual const char *getVAListDeclaration() const {
     return "typedef void* __builtin_va_list;";
   }

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=149086&r1=149085&r2=149086&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Jan 26 16:14:27 2012
@@ -238,7 +238,8 @@
     Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
 
     llvm::Type *ResultType = ConvertType(E->getType());
-    Value *Result = Builder.CreateCall2(F, ArgValue, Builder.getTrue());
+    Value *ZeroUndef = Builder.getInt1(Target.isCLZForZeroUndef());
+    Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef);
     if (Result->getType() != ResultType)
       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
                                      "cast");
@@ -253,7 +254,8 @@
     Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
 
     llvm::Type *ResultType = ConvertType(E->getType());
-    Value *Result = Builder.CreateCall2(F, ArgValue, Builder.getTrue());
+    Value *ZeroUndef = Builder.getInt1(Target.isCLZForZeroUndef());
+    Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef);
     if (Result->getType() != ResultType)
       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
                                      "cast");

Modified: cfe/trunk/test/CodeGen/builtin-count-zeros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtin-count-zeros.c?rev=149086&r1=149085&r2=149086&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/builtin-count-zeros.c (original)
+++ cfe/trunk/test/CodeGen/builtin-count-zeros.c Thu Jan 26 16:14:27 2012
@@ -1,4 +1,8 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | grep 'cttz' | count 2
-// RUN: %clang_cc1 -emit-llvm %s -o - | grep 'ctlz' | count 2
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-ARM
 
 int a(int a) {return __builtin_ctz(a) + __builtin_clz(a);}
+// CHECK: call i32 @llvm.cttz.i32({{.*}}, i1 true)
+// CHECK: call i32 @llvm.ctlz.i32({{.*}}, i1 true)
+// CHECK-ARM: call i32 @llvm.cttz.i32({{.*}}, i1 false)
+// CHECK-ARM: call i32 @llvm.ctlz.i32({{.*}}, i1 false)





More information about the cfe-commits mailing list