ac/llvm: add better code for fsign
[mesa.git] / src / amd / llvm / ac_llvm_helper.cpp
index f5383344dd4f3c37348449d0eb28c61dd6d3699d..184f76a796815e39aad23836842c240cab92b5b4 100644 (file)
 
 #include <cstring>
 
-#include "ac_binary.h"
-#include "ac_llvm_util.h"
-#include "ac_llvm_build.h"
-
-#include "util/macros.h"
-
 #include <llvm-c/Core.h>
 #include <llvm/Target/TargetMachine.h>
 #include <llvm/IR/IRBuilder.h>
 
 #include <llvm/IR/LegacyPassManager.h>
 
+/* DO NOT REORDER THE HEADERS
+ * The LLVM headers need to all be included before any Mesa header,
+ * as they use the `restrict` keyword in ways that are incompatible
+ * with our #define in include/c99_compat.h
+ */
+
+#include "ac_binary.h"
+#include "ac_llvm_util.h"
+#include "ac_llvm_build.h"
+
+#include "util/macros.h"
+
 void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes)
 {
    llvm::Argument *A = llvm::unwrap<llvm::Argument>(val);
    A->addAttr(llvm::Attribute::getWithDereferenceableBytes(A->getContext(), bytes));
 }
 
+void ac_add_attr_alignment(LLVMValueRef val, uint64_t bytes)
+{
+#if LLVM_VERSION_MAJOR >= 10
+       llvm::Argument *A = llvm::unwrap<llvm::Argument>(val);
+       A->addAttr(llvm::Attribute::getWithAlignment(A->getContext(), llvm::Align(bytes)));
+#else
+       /* Avoid unused parameter warnings. */
+       (void)val;
+       (void)bytes;
+#endif
+}
+
 bool ac_is_sgpr_param(LLVMValueRef arg)
 {
        llvm::Argument *A = llvm::unwrap<llvm::Argument>(arg);
@@ -96,11 +114,6 @@ LLVMBuilderRef ac_create_builder(LLVMContextRef ctx,
                 */
                flags.setAllowReciprocal(); /* arcp */
 
-               /* Allow floating-point contraction (e.g. fusing a multiply
-                * followed by an addition into a fused multiply-and-add).
-                */
-               flags.setAllowContract(); /* contract */
-
                llvm::unwrap(builder)->setFastMathFlags(flags);
                break;
        }
@@ -108,30 +121,29 @@ LLVMBuilderRef ac_create_builder(LLVMContextRef ctx,
        return builder;
 }
 
-/* Return the original state of inexact math. */
-bool ac_disable_inexact_math(LLVMBuilderRef builder)
+void ac_enable_signed_zeros(struct ac_llvm_context *ctx)
 {
-       auto *b = llvm::unwrap(builder);
-       llvm::FastMathFlags flags = b->getFastMathFlags();
-
-       if (!flags.allowContract())
-               return false;
+       if (ctx->float_mode == AC_FLOAT_MODE_DEFAULT_OPENGL) {
+               auto *b = llvm::unwrap(ctx->builder);
+               llvm::FastMathFlags flags = b->getFastMathFlags();
 
-       flags.setAllowContract(false);
-       b->setFastMathFlags(flags);
-       return true;
+               /* This disables the optimization of (x + 0), which is used
+                * to convert negative zero to positive zero.
+                */
+               flags.setNoSignedZeros(false);
+               b->setFastMathFlags(flags);
+       }
 }
 
-void ac_restore_inexact_math(LLVMBuilderRef builder, bool value)
+void ac_disable_signed_zeros(struct ac_llvm_context *ctx)
 {
-       auto *b = llvm::unwrap(builder);
-       llvm::FastMathFlags flags = b->getFastMathFlags();
-
-       if (flags.allowContract() == value)
-               return;
+       if (ctx->float_mode == AC_FLOAT_MODE_DEFAULT_OPENGL) {
+               auto *b = llvm::unwrap(ctx->builder);
+               llvm::FastMathFlags flags = b->getFastMathFlags();
 
-       flags.setAllowContract(value);
-       b->setFastMathFlags(flags);
+               flags.setNoSignedZeros();
+               b->setFastMathFlags(flags);
+       }
 }
 
 LLVMTargetLibraryInfoRef