Browse Source

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

Xiang Li 8 years ago
parent
commit
843b64b320

+ 50 - 2
docs/DXIL.rst

@@ -1934,8 +1934,8 @@ ID  Name                          Description
 32  FirstbitLo                    returns the FirstbitLo
 32  FirstbitLo                    returns the FirstbitLo
 33  FirstbitHi                    returns src != 0? (BitWidth-1 - FirstbitHi) : -1
 33  FirstbitHi                    returns src != 0? (BitWidth-1 - FirstbitHi) : -1
 34  FirstbitSHi                   returns src != 0? (BitWidth-1 - FirstbitSHi) : -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
 37  IMax                          returns the IMax of the input values
 38  IMin                          returns the IMin of the input values
 38  IMin                          returns the IMin of the input values
 39  UMax                          returns the UMax 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.
 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.
 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
 Saturate
 ~~~~~~~~
 ~~~~~~~~
 
 

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

@@ -254,8 +254,8 @@ namespace DXIL {
   // Enumeration for operations specified by DXIL
   // Enumeration for operations specified by DXIL
   enum class OpCode : unsigned {
   enum class OpCode : unsigned {
     // Binary float
     // 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
     // Binary int with two outputs
     IMul = 41, // returns the IMul of the input values
     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); }
   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 {
 struct DxilInst_FMax {
   const llvm::Instruction *Instr;
   const llvm::Instruction *Instr;
   // Construction and identification
   // Construction and identification
@@ -1347,7 +1347,7 @@ struct DxilInst_FMax {
   llvm::Value *get_b() const { return Instr->getOperand(2); }
   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 {
 struct DxilInst_FMin {
   const llvm::Instruction *Instr;
   const llvm::Instruction *Instr;
   // Construction and identification
   // 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());
       CallInst *CI = cast<CallInst>(*F.user_begin());
       OpCode OpCode = OP::GetDxilOpFuncCallInst(CI);
       OpCode OpCode = OP::GetDxilOpFuncCallInst(CI);
       Type *pOverloadType = OP::GetOverloadType(OpCode, &F);
       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::UAddc:
   case OpCode::USubb:
   case OpCode::USubb:
   case OpCode::WaveActiveAllEqual:
   case OpCode::WaveActiveAllEqual:
+    DXASSERT_NOMSG(FT->getNumParams() > 1);
     return FT->getParamType(1);
     return FT->getParamType(1);
   case OpCode::TempRegStore:
   case OpCode::TempRegStore:
+    DXASSERT_NOMSG(FT->getNumParams() > 2);
     return FT->getParamType(2);
     return FT->getParamType(2);
   case OpCode::MinPrecXRegStore:
   case OpCode::MinPrecXRegStore:
   case OpCode::StoreOutput:
   case OpCode::StoreOutput:
   case OpCode::BufferStore:
   case OpCode::BufferStore:
   case OpCode::StorePatchConstant:
   case OpCode::StorePatchConstant:
+    DXASSERT_NOMSG(FT->getNumParams() > 4);
     return FT->getParamType(4);
     return FT->getParamType(4);
   case OpCode::TextureStore:
   case OpCode::TextureStore:
+    DXASSERT_NOMSG(FT->getNumParams() > 5);
     return FT->getParamType(5);
     return FT->getParamType(5);
   case OpCode::MakeDouble:
   case OpCode::MakeDouble:
   case OpCode::SplitDouble:
   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)",
       {"dx.op.coverage.i32(i32 91)",
        "declare i32 @dx.op.coverage.i32(i32)"
        "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.coverage.i32(i32)\n"
-       "declare i32 @dx.op.innercoverage.i32(i32)"
+       "declare i32 @dx.op.innerCoverage.i32(i32)"
       },
       },
       "InnerCoverage and Coverage are mutually exclusive.");
       "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                           |
 | a    | b                           |
 |      +------+--------+------+------+
 |      +------+--------+------+------+
 |      | -inf | F      | +inf | NaN  |
 |      | -inf | F      | +inf | NaN  |
-------+------+--------+------+------+
++------+------+--------+------+------+
 | -inf | -inf | b      | +inf | -inf |
 | -inf | -inf | b      | +inf | -inf |
 +------+------+--------+------+------+
 +------+------+--------+------+------+
 | F    | a    | a or b | +inf | a    |
 | 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:
             for opcode in opcodes:
                 line = line + "case OpCode::{name}".format(name = opcode + ":\n")
                 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) + ");"
             line = line + "  return FT->getParamType(" + str(index) + ");"
             print(line)
             print(line)