Index: bindings/ocaml/llvm/llvm.ml =================================================================== --- bindings/ocaml/llvm/llvm.ml +++ bindings/ocaml/llvm/llvm.ml @@ -276,6 +276,16 @@ | Instruction of Opcode.t end +module FastMathFlags = struct + type t = + | Clear + | Fast + | Nnan + | Ninf + | NSZ + | Arcp +end + exception IoError of string external register_exns : exn -> unit = "llvm_register_core_exns" @@ -441,6 +451,17 @@ external is_undef : llvalue -> bool = "llvm_is_undef" external constexpr_opcode : llvalue -> Opcode.t = "llvm_constexpr_get_opcode" +(*--... Operations on fast math operators...................................--*) + +external set_fastmathflag : llvalue -> FastMathFlags.t -> unit + = "llvm_set_fastmathflag" +external get_fastmathflags : llvalue -> FastMathFlags.t array + = "llvm_get_fastmathflag" +external has_fastmathflags : llvalue -> bool + = "llvm_has_fastmathflags" +external has_fastmathflag : llvalue -> FastMathFlags.t -> bool + = "llvm_has_fastmathflag" + (*--... Operations on instructions .........................................--*) external has_metadata : llvalue -> bool = "llvm_has_metadata" external metadata : llvalue -> llmdkind -> llvalue option = "llvm_metadata" Index: bindings/ocaml/llvm/llvm.mli =================================================================== --- bindings/ocaml/llvm/llvm.mli +++ bindings/ocaml/llvm/llvm.mli @@ -343,6 +343,15 @@ | Instruction of Opcode.t end +module FastMathFlags: sig + type t = + | Clear + | Fast (* Unsafe algebra -> no verification -> fast*) + | Nnan (* Not a nan value *) + | Ninf (* Not an infinite value *) + | NSZ (* No signed zeros *) + | Arcp (* Allow algebraically optimization *) +end (** {6 Iteration} *) @@ -764,6 +773,23 @@ value [v], or [Opcode.Invalid] if [v] is not a constexpr. *) val constexpr_opcode : llvalue -> Opcode.t +(** {7 Operations on fast math operators} *) + +(** [set_fastmathflag v fmf] adds [fmf] FastMathFlags.t as [v] llvalue + fast math operator. *) +val set_fastmathflag : llvalue -> FastMathFlags.t -> unit + +(** [get_fastmathflags v ] returns an array of FastMathFlags.t for + a given [v] llvalue fast math operator. *) +val get_fastmathflags : llvalue -> FastMathFlags.t array + +(** [has_fastmathflags v ] returns true if the [v] llvalue + fast math operator contains any fast mast flag. *) +val has_fastmathflags : llvalue -> bool + +(** [has_fastmathflag v fmf] returns true if the [v] llvalue + fast math operator contains the [fmf] FastMathFlags.t flag *) +val has_fastmathflag : llvalue -> FastMathFlags.t -> bool (** {7 Operations on instructions} *) Index: bindings/ocaml/llvm/llvm_ocaml.c =================================================================== --- bindings/ocaml/llvm/llvm_ocaml.c +++ bindings/ocaml/llvm/llvm_ocaml.c @@ -611,6 +611,31 @@ Val_int(LLVMGetConstOpcode(Val)) : Val_int(0); } +/*--... Operations on Fast Math operator ...................................--*/ + +/* llvalue -> FastMathFlags.t -> unit */ +CAMLprim value llvm_set_fastmathflag(LLVMValueRef Val, value Flag){ + LLVMSetFastMathFlag(Val, Int_val(Flag)); + return Val_unit; +} + +/* llvalue -> FastMathFlags.t array */ +CAMLprim value llvm_get_fastmathflags(LLVMValueRef Val){ + value Flags = alloc(LLVMCountFastMathFlags(Val), 0); + LLVMGetFastMathFlags(Val, (LLVMFastMathFlags*) Flags); + return Flags; +} + +/* llvalue -> bool */ +CAMLprim value llvm_has_fastmathflags(LLVMValueRef Val) { + return Val_bool(LLVMHasFastMathFlags(Val)); +} + +/* llvalue -> FastMathFlags.t -> bool */ +CAMLprim value llvm_has_fastmathflag(LLVMValueRef Val, value Flag) { + return Val_bool(LLVMHasFastMathFlag(Val, Flag)); +} + /*--... Operations on instructions .........................................--*/ /* llvalue -> bool */ @@ -643,7 +668,6 @@ return Val_unit; } - /*--... Operations on metadata .............................................--*/ /* llcontext -> string -> llvalue */ Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -415,6 +415,16 @@ LLVMDSNote } LLVMDiagnosticSeverity; +typedef enum { + LLVMFastMathFlagsNone = 0, + LLVMFastMathFlagsAllowAlgebra, + LLVMFastMathFlagsNoNaN, + LLVMFastMathFlagsNoInf, + LLVMFastMathFlagsNoSignedZero, + LLVMFastMathFlagsAllowReciprocal +} LLVMFastMathFlags; + + /** * @} */ @@ -2323,6 +2333,69 @@ */ void LLVMSetMetadata(LLVMValueRef Val, unsigned KindID, LLVMValueRef Node); +/** + * Set the fast math flags in Dest for an individual instruction. + * + * This only returns something if concerned operator is a + * FastMathoperator extension as frem, fadd, fdiv and fsub. + * + * @see llvm::Instruction::getFastMathFlags() + */ +void LLVMGetFastMathFlags(LLVMValueRef Inst, LLVMFastMathFlags* Dest); + +/** + * Returns the number of fast math flags setting for an instruction. + * + * This only returns something if concerned operator is a + * FastMathoperator extension as frem, fadd, fdiv and fsub. + * + */ +int LLVMCountFastMathFlags(LLVMValueRef Inst); + +/** + * Returns n != 0 if the individual instruction contains fast math flags. + * + * This only returns something if concerned operator is a + * FastMathoperator extension as frem, fadd, fdiv and fsub. + * + * @see llvm::Instruction::hasUnsafeAlgebra() + * @see llvm::Instruction::hasNoNans() + * @see llvm::Instruction::hasNoInfs() + * @see llvm::Instruction::hasNoSignedZeros() + * @see llvm::Instruction::hasAllowReciproval() + */ +int LLVMHasFastMathFlag(LLVMValueRef Inst, LLVMFastMathFlags FMF); + +/** + * Returns n != 0 if the individual instruction contains fast math flags. + * + * This only returns something if concerned operator is a + * FastMathoperator extension as frem, fadd, fdiv and fsub. + * + * @see llvm::Instruction::hasUnsafeAlgebra() + * @see llvm::Instruction::hasNoNans() + * @see llvm::Instruction::hasNoInfs() + * @see llvm::Instruction::hasNoSignedZeros() + * @see llvm::Instruction::hasAllowReciproval() + */ +int LLVMHasFastMathFlags(LLVMValueRef Inst); + +/** + * Set an uniq fast math flag on an individual instruction. + * + * This only returns something if concerned operator is a + * FastMathoperator extension as frem, fadd, fdiv and fsub. + * + * @see llvm::Instruction::setFastMathFlags() + * @see llvm::Instruction::setUnsafeAlgebra() + * @see llvm::Instruction::setNoNans() + * @see llvm::Instruction::setNoInfs() + * @see llvm::Instruction::setNoSignedZeros() + * @see llvm::Instruction::setAllowReciproval() + * @see llvm::FastMathFlags::clear() + */ +void LLVMSetFastMathFlag(LLVMValueRef Inst, LLVMFastMathFlags FMF); + /** * Obtain the basic block to which an instruction belongs. * Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -562,6 +562,104 @@ MD ? unwrap(MD) : nullptr); } + +/*--... Operations on Fast Math operator ...................................--*/ + +int LLVMHasFastMathFlags(LLVMValueRef Inst) { + return + (unwrap(Inst)->hasUnsafeAlgebra() + || unwrap(Inst)->hasNoNaNs() + || unwrap(Inst)->hasNoInfs() + || unwrap(Inst)->hasNoSignedZeros() + || unwrap(Inst)->hasAllowReciprocal()); +} + + +int LLVMHasFastMathFlag(LLVMValueRef Inst, LLVMFastMathFlags Flag) { + switch(Flag){ + case LLVMFastMathFlagsAllowAlgebra: + return unwrap(Inst)->hasUnsafeAlgebra(); + break; + case LLVMFastMathFlagsNoNaN: + return unwrap(Inst)->hasNoNaNs(); + break; + case LLVMFastMathFlagsNoInf: + return unwrap(Inst)->hasNoInfs(); + break; + case LLVMFastMathFlagsNoSignedZero: + return unwrap(Inst)->hasNoSignedZeros(); + break; + case LLVMFastMathFlagsAllowReciprocal: + return unwrap(Inst)->hasAllowReciprocal(); + break; + default: return (LLVMHasFastMathFlags(Inst) == 0); + break; + } + +} + +void LLVMSetFastMathFlag(LLVMValueRef Inst, LLVMFastMathFlags Flag){ + switch(Flag){ + case LLVMFastMathFlagsAllowAlgebra: + unwrap(Inst)->setHasUnsafeAlgebra(true); + break; + case LLVMFastMathFlagsNoNaN: + unwrap(Inst)->setHasNoNaNs(true); + break; + case LLVMFastMathFlagsNoInf: + unwrap(Inst)->setHasNoInfs(true); + break; + case LLVMFastMathFlagsNoSignedZero: + unwrap(Inst)->setHasNoSignedZeros(true); + break; + case LLVMFastMathFlagsAllowReciprocal: + unwrap(Inst)->setHasAllowReciprocal(true); + break; + default: /* default LLVMFastMathFlagsNone = llvm.ml*::*::Clear */ + FastMathFlags fmf = + (unwrap(Inst)->getFastMathFlags()); + fmf.clear(); + unwrap(Inst)->setFastMathFlags(fmf); + break; + } +} + + +int LLVMCountFastMathFlags(LLVMValueRef Inst){ + if (LLVMHasFastMathFlags(Inst) != 0) { + unsigned res = 0; + FastMathFlags fmf = + (unwrap(Inst)->getFastMathFlags()); + if(fmf.noNaNs()) res++; + if(fmf.noInfs()) res++; + if(fmf.noSignedZeros()) res++; + if(fmf.allowReciprocal()) res++; + if(fmf.unsafeAlgebra()) res++; + return res; + } + return 0; +} + +/* returns an array of FMF.t through Dest */ +void LLVMGetFastMathFlags(LLVMValueRef Inst, LLVMFastMathFlags* Dest){ + if (LLVMHasFastMathFlags(Inst) != 0) { + unsigned i = 0; + FastMathFlags fmf = + (unwrap(Inst)->getFastMathFlags()); + if(fmf.noNaNs()) + Dest[i++] = (LLVMFastMathFlagsNoNaN); + if(fmf.noInfs()) + Dest[i++] = (LLVMFastMathFlagsNoInf); + if(fmf.noSignedZeros()) + Dest[i++] = (LLVMFastMathFlagsNoSignedZero); + if(fmf.allowReciprocal()) + Dest[i++] = (LLVMFastMathFlagsAllowReciprocal); + if(fmf.unsafeAlgebra()) + Dest[i++] = (LLVMFastMathFlagsAllowAlgebra); + } +} + + /*--.. Conversion functions ................................................--*/ #define LLVM_DEFINE_VALUE_CAST(name) \