소스 검색

Check exist function match dxil operation function when refresh operation fucntion cache. (#108)

Xiang Li 8 년 전
부모
커밋
843b64b320

+ 50 - 2
docs/DXIL.rst

@@ -1934,8 +1934,8 @@ ID  Name                          Description
 32  FirstbitLo                    returns the FirstbitLo
 33  FirstbitHi                    returns src != 0? (BitWidth-1 - FirstbitHi) : -1
 34  FirstbitSHi                   returns src != 0? (BitWidth-1 - FirstbitSHi) : -1
-35  FMax                          returns the FMax of the input values
-36  FMin                          returns the FMin of the input values
+35  FMax                          returns a if a >= b, else b
+36  FMin                          returns a if a < b, else b
 37  IMax                          returns the IMax of the input values
 38  IMin                          returns the IMin of the input values
 39  UMax                          returns the UMax of the input values
@@ -2059,6 +2059,54 @@ FAbs
 The FAbs instruction takes simply forces the sign of the number(s) on the source operand positive, including on INF values.
 Applying FAbs on NaN preserves NaN, although the particular NaN bit pattern that results is not defined.
 
+FMax
+~~~~
+
+>= is used instead of > so that if min(x,y) = x then max(x,y) = y.
+
+NaN has special handling: If one source operand is NaN, then the other source operand is returned.
+If both are NaN, any NaN representation is returned.
+This conforms to new IEEE 754R rules.
+
+Denorms are flushed (sign preserved) before comparison, however the result written to dest may or may not be denorm flushed.
+
++------+-----------------------------+
+| a    | b                           |
+|      +------+--------+------+------+
+|      | -inf | F      | +inf | NaN  |
++------+------+--------+------+------+
+| -inf | -inf | b      | +inf | -inf |
++------+------+--------+------+------+
+| F    | a    | a or b | +inf | a    |
++------+------+--------+------+------+
+| +inf | +inf | +inf   | +inf | +inf |
++------+------+--------+------+------+
+| NaN  | -inf | b      | +inf | NaN  |
++------+------+--------+------+------+
+
+FMin
+~~~~
+
+NaN has special handling: If one source operand is NaN, then the other source operand is returned.
+If both are NaN, any NaN representation is returned.
+This conforms to new IEEE 754R rules.
+
+Denorms are flushed (sign preserved) before comparison, however the result written to dest may or may not be denorm flushed.
+
++------+-----------------------------+
+| a    | b                           |
+|      +------+--------+------+------+
+|      | -inf | F      | +inf | NaN  |
++------+------+--------+------+------+
+| -inf | -inf | -inf   | -inf | -inf |
++------+------+--------+------+------+
+| F    | -inf | a or b |    a |    a |
++------+------+--------+------+------+
+| +inf | -inf | b      | +inf | +inf |
++------+------+--------+------+------+
+| NaN  | -inf | b      | +inf | NaN  |
++------+------+--------+------+------+
+
 Saturate
 ~~~~~~~~
 

+ 2 - 2
include/dxc/HLSL/DxilConstants.h

@@ -254,8 +254,8 @@ namespace DXIL {
   // Enumeration for operations specified by DXIL
   enum class OpCode : unsigned {
     // Binary float
-    FMax = 35, // returns the FMax of the input values
-    FMin = 36, // returns the FMin of the input values
+    FMax = 35, // returns a if a >= b, else b
+    FMin = 36, // returns a if a < b, else b
   
     // Binary int with two outputs
     IMul = 41, // returns the IMul of the input values

+ 2 - 2
include/dxc/HLSL/DxilInstructions.h

@@ -1328,7 +1328,7 @@ struct DxilInst_FirstbitSHi {
   llvm::Value *get_value() const { return Instr->getOperand(1); }
 };
 
-/// This instruction returns the FMax of the input values
+/// This instruction returns a if a >= b, else b
 struct DxilInst_FMax {
   const llvm::Instruction *Instr;
   // Construction and identification
@@ -1347,7 +1347,7 @@ struct DxilInst_FMax {
   llvm::Value *get_b() const { return Instr->getOperand(2); }
 };
 
-/// This instruction returns the FMin of the input values
+/// This instruction returns a if a < b, else b
 struct DxilInst_FMin {
   const llvm::Instruction *Instr;
   // Construction and identification

+ 6 - 12
lib/HLSL/DxilOperations.cpp

@@ -420,18 +420,8 @@ void OP::RefreshCache(llvm::Module *pModule) {
       CallInst *CI = cast<CallInst>(*F.user_begin());
       OpCode OpCode = OP::GetDxilOpFuncCallInst(CI);
       Type *pOverloadType = OP::GetOverloadType(OpCode, &F);
-
-      DXASSERT(0 <= (unsigned)OpCode && OpCode < OpCode::NumOpCodes,
-               "otherwise caller passed OOB OpCode");
-      _Analysis_assume_(0 <= (unsigned)OpCode && OpCode < OpCode::NumOpCodes);
-      DXASSERT(IsOverloadLegal(OpCode, pOverloadType),
-               "otherwise the caller requested illegal operation overload (eg "
-               "HLSL function with unsupported types for mapped intrinsic "
-               "function)");
-      unsigned TypeSlot = GetTypeSlot(pOverloadType);
-      OpCodeClass opClass = m_OpCodeProps[(unsigned)OpCode].OpCodeClass;
-      m_OpCodeClassCache[(unsigned)opClass].pOverloads[TypeSlot] = &F;
-      m_FunctionToOpClass[&F] = opClass;
+      Function *OpFunc = GetOpFunc(OpCode, pOverloadType);
+      DXASSERT_NOMSG(OpFunc == &F);
     }
   }
 }
@@ -744,15 +734,19 @@ llvm::Type *OP::GetOverloadType(OpCode OpCode, llvm::Function *F) {
   case OpCode::UAddc:
   case OpCode::USubb:
   case OpCode::WaveActiveAllEqual:
+    DXASSERT_NOMSG(FT->getNumParams() > 1);
     return FT->getParamType(1);
   case OpCode::TempRegStore:
+    DXASSERT_NOMSG(FT->getNumParams() > 2);
     return FT->getParamType(2);
   case OpCode::MinPrecXRegStore:
   case OpCode::StoreOutput:
   case OpCode::BufferStore:
   case OpCode::StorePatchConstant:
+    DXASSERT_NOMSG(FT->getNumParams() > 4);
     return FT->getParamType(4);
   case OpCode::TextureStore:
+    DXASSERT_NOMSG(FT->getNumParams() > 5);
     return FT->getParamType(5);
   case OpCode::MakeDouble:
   case OpCode::SplitDouble:

+ 2 - 2
tools/clang/unittests/HLSL/ValidationTest.cpp

@@ -731,9 +731,9 @@ TEST_F(ValidationTest, InnerCoverageFail) {
       {"dx.op.coverage.i32(i32 91)",
        "declare i32 @dx.op.coverage.i32(i32)"
       },
-      {"dx.op.coverage.i32(i32 91)\n  %inner = call i32 @dx.op.innercoverage.i32(i32 92)",
+      {"dx.op.coverage.i32(i32 91)\n  %inner = call i32 @dx.op.innerCoverage.i32(i32 92)",
        "declare i32 @dx.op.coverage.i32(i32)\n"
-       "declare i32 @dx.op.innercoverage.i32(i32)"
+       "declare i32 @dx.op.innerCoverage.i32(i32)"
       },
       "InnerCoverage and Coverage are mutually exclusive.");
 }

+ 1 - 1
utils/hct/hctdb_inst_docs.txt

@@ -44,7 +44,7 @@ Denorms are flushed (sign preserved) before comparison, however the result writt
 | a    | b                           |
 |      +------+--------+------+------+
 |      | -inf | F      | +inf | NaN  |
-------+------+--------+------+------+
++------+------+--------+------+------+
 | -inf | -inf | b      | +inf | -inf |
 +------+------+--------+------+------+
 | F    | a    | a or b | +inf | a    |

+ 1 - 0
utils/hct/hctdb_instrhelp.py

@@ -471,6 +471,7 @@ class db_oload_gen:
             for opcode in opcodes:
                 line = line + "case OpCode::{name}".format(name = opcode + ":\n")
 
+            line = line + "  DXASSERT_NOMSG(FT->getNumParams() > " + str(index) + ");\n"
             line = line + "  return FT->getParamType(" + str(index) + ");"
             print(line)