gallivm: Workaround LLVM PR 27332.
authorJose Fonseca <jfonseca@vmware.com>
Wed, 13 Apr 2016 14:41:55 +0000 (15:41 +0100)
committerJose Fonseca <jfonseca@vmware.com>
Wed, 13 Apr 2016 15:42:55 +0000 (16:42 +0100)
The credit for finding and isolating this bug goes to Vinson and Roland.

The buggy LLVM versions were found by doing

  opt -instcombine llvm-pr27332.ll > /dev/null

where llvm-pr27332.ll is the IR from
https://llvm.org/bugs/show_bug.cgi?id=27332#c3

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/auxiliary/gallivm/lp_bld_arit.c

index 9cb745e4cfe8779cc2fbc271478f79cc5c78b5b6..beff4143fd8cc17ae3b53ccc88835c30dc203f15 100644 (file)
@@ -1492,9 +1492,20 @@ lp_build_abs(struct lp_build_context *bld,
       return a;
 
    if(type.floating) {
-      char intrinsic[32];
-      lp_format_intrinsic(intrinsic, sizeof intrinsic, "llvm.fabs", vec_type);
-      return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a);
+      if (0x0306 <= HAVE_LLVM && HAVE_LLVM < 0x0309) {
+         /* Workaround llvm.org/PR27332 */
+         LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->gallivm, type);
+         unsigned long long absMask = ~(1ULL << (type.width - 1));
+         LLVMValueRef mask = lp_build_const_int_vec(bld->gallivm, type, ((unsigned long long) absMask));
+         a = LLVMBuildBitCast(builder, a, int_vec_type, "");
+         a = LLVMBuildAnd(builder, a, mask, "");
+         a = LLVMBuildBitCast(builder, a, vec_type, "");
+         return a;
+      } else {
+         char intrinsic[32];
+         lp_format_intrinsic(intrinsic, sizeof intrinsic, "llvm.fabs", vec_type);
+         return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a);
+      }
    }
 
    if(type.width*type.length == 128 && util_cpu_caps.has_ssse3) {