llvmpipe: Fallback to element-wise comparisons when no comparison intrinsic is available.
authorJosé Fonseca <jfonseca@vmware.com>
Mon, 31 Aug 2009 09:22:36 +0000 (10:22 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Mon, 31 Aug 2009 09:22:36 +0000 (10:22 +0100)
Although selection of vector elements is valid LLVM IR, no machine target
supports it yet.

This is a last-resort option, but it allows llvmpipe to be used on any
target supported by LLVM without modifications. Obviously better
performance is attainable by emitting SIMD intrinsics where otherwise
LLVM doesn't.

src/gallium/drivers/llvmpipe/lp_bld_logic.c

index d6dfd853422df269f3d8fe0e575dce2615a39650..8631efd6c3eb35d16d914108412202d982b7f4ba 100644 (file)
@@ -51,6 +51,8 @@ lp_build_cmp(struct lp_build_context *bld,
    LLVMValueRef zeros = LLVMConstNull(int_vec_type);
    LLVMValueRef ones = LLVMConstAllOnes(int_vec_type);
    LLVMValueRef cond;
+   LLVMValueRef res;
+   unsigned i;
 
    if(func == PIPE_FUNC_NEVER)
       return zeros;
@@ -67,7 +69,6 @@ lp_build_cmp(struct lp_build_context *bld,
          LLVMValueRef args[3];
          unsigned cc;
          boolean swap;
-         LLVMValueRef res;
 
          swap = FALSE;
          switch(func) {
@@ -218,7 +219,28 @@ lp_build_cmp(struct lp_build_context *bld,
          assert(0);
          return bld->undef;
       }
+
+#if 0
+      /* XXX: Although valid IR, no LLVM target currently support this */
       cond = LLVMBuildFCmp(bld->builder, op, a, b, "");
+      res = LLVMBuildSelect(bld->builder, cond, ones, zeros, "");
+#else
+      debug_printf("%s: warning: using slow element-wise vector comparison\n",
+                   __FUNCTION__);
+      res = LLVMGetUndef(int_vec_type);
+      for(i = 0; i < type.length; ++i) {
+         LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+         cond = LLVMBuildFCmp(bld->builder, op,
+                              LLVMBuildExtractElement(bld->builder, a, index, ""),
+                              LLVMBuildExtractElement(bld->builder, b, index, ""),
+                              "");
+         cond = LLVMBuildSelect(bld->builder, cond,
+                                LLVMConstExtractElement(ones, index),
+                                LLVMConstExtractElement(zeros, index),
+                                "");
+         res = LLVMBuildInsertElement(bld->builder, res, cond, index, "");
+      }
+#endif
    }
    else {
       LLVMIntPredicate op;
@@ -245,10 +267,31 @@ lp_build_cmp(struct lp_build_context *bld,
          assert(0);
          return bld->undef;
       }
+
+#if 0
+      /* XXX: Although valid IR, no LLVM target currently support this */
       cond = LLVMBuildICmp(bld->builder, op, a, b, "");
+      res = LLVMBuildSelect(bld->builder, cond, ones, zeros, "");
+#else
+      debug_printf("%s: warning: using slow element-wise vector comparison\n",
+                   __FUNCTION__);
+      res = LLVMGetUndef(int_vec_type);
+      for(i = 0; i < type.length; ++i) {
+         LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+         cond = LLVMBuildICmp(bld->builder, op,
+                              LLVMBuildExtractElement(bld->builder, a, index, ""),
+                              LLVMBuildExtractElement(bld->builder, b, index, ""),
+                              "");
+         cond = LLVMBuildSelect(bld->builder, cond,
+                                LLVMConstExtractElement(ones, index),
+                                LLVMConstExtractElement(zeros, index),
+                                "");
+         res = LLVMBuildInsertElement(bld->builder, res, cond, index, "");
+      }
+#endif
    }
 
-   return LLVMBuildSelect(bld->builder, cond, ones, zeros, "");
+   return res;
 }