Bläddra i källkod

Expand tan to sin/cos in DxilExpandTrigIntrinsics. (#343)

Xiang Li 8 år sedan
förälder
incheckning
9c8aca547a

+ 24 - 0
lib/HLSL/DxilExpandTrigIntrinsics.cpp

@@ -89,6 +89,7 @@ private:
   Value *expandHCos(IRBuilder<> &builder, DxilInst_Hcos hcos, DxilModule &DM);
   Value *expandHSin(IRBuilder<> &builder, DxilInst_Hsin hsin, DxilModule &DM);
   Value *expandHTan(IRBuilder<> &builder, DxilInst_Htan htan, DxilModule &DM);
+  Value *expandTan(IRBuilder<> &builder, DxilInst_Tan tan, DxilModule &DM);
 };
 
 // Math constants.
@@ -119,6 +120,7 @@ CallInst *DxilExpandTrigIntrinsics::isExpandableTrigIntrinsicCall(Instruction *I
       case OP::OpCode::Hcos:
       case OP::OpCode::Hsin:
       case OP::OpCode::Htan:
+      case OP::OpCode::Tan:
         return cast<CallInst>(I);
       default: break;
       }
@@ -168,6 +170,7 @@ bool DxilExpandTrigIntrinsics::expandTrigIntrinsics(DxilModule &DM, const Intrin
     case OP::OpCode::Hcos: expansion = expandHCos(builder, intrinsic, DM); break;
     case OP::OpCode::Hsin: expansion = expandHSin(builder, intrinsic, DM); break;
     case OP::OpCode::Htan: expansion = expandHTan(builder, intrinsic, DM); break;
+    case OP::OpCode::Tan: expansion = expandTan(builder, intrinsic, DM); break;
     default:
       assert(false && "unexpected intrinsic");
       break;
@@ -508,6 +511,27 @@ Value *DxilExpandTrigIntrinsics::expandHTan(IRBuilder<> &builder, DxilInst_Htan
   return r;
 }
 
+// Tan
+// ----------------------------------------------------------------------------
+// We use the following identity for computing tan(x)
+//
+//    tan(x) = sin(x) / cos(x)
+//
+// No range reduction is needed.
+//
+Value *DxilExpandTrigIntrinsics::expandTan(IRBuilder<> &builder,
+                                           DxilInst_Tan tan, DxilModule &DM) {
+  assert(tan);
+  StringRef name = "tan.x";
+  Value *X = tan.get_value();
+  OP *dxOp = DM.GetOP();
+  Value *sin = emitUnaryFloat(builder, X, dxOp, OP::OpCode::Sin, name);
+  Value *cos = emitUnaryFloat(builder, X, dxOp, OP::OpCode::Cos, name);
+  Value *r = builder.CreateFDiv(sin, cos, name);
+
+  return r;
+}
+
 char DxilExpandTrigIntrinsics::ID = 0;
 
 FunctionPass *llvm::createDxilExpandTrigIntrinsicsPass() {

+ 11 - 0
tools/clang/test/HLSL/expand_trig/tan.hlsl

@@ -0,0 +1,11 @@
+// RUN: %dxc -Emain -Tps_6_0 %s | %opt -S -hlsl-dxil-expand-trig-intrinsics | %FileCheck %s
+
+// CHECK: [[r0:%.*]]  = call float @dx.op.unary.f32(i32 13
+// CHECK: [[r1:%.*]]  = call float @dx.op.unary.f32(i32 12
+// CHECK: fdiv fast float [[r0]], [[r1]]
+// CHECK-NOT: call float @dx.op.unary.f32(i32 14
+
+[RootSignature("")]
+float main(float x : A) : SV_Target {
+    return tan(x);
+}

+ 1 - 0
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -2544,6 +2544,7 @@ TEST_F(CompilerTest, CodeGenExpandTrig) {
   CodeGenTestCheck(L"expand_trig\\hsin_h.hlsl");
   CodeGenTestCheck(L"expand_trig\\htan.hlsl");
   CodeGenTestCheck(L"expand_trig\\htan_h.hlsl");
+  CodeGenTestCheck(L"expand_trig\\tan.hlsl");
   CodeGenTestCheck(L"expand_trig\\keep_precise.0.hlsl");
   CodeGenTestCheck(L"expand_trig\\keep_precise.1.hlsl");
 }