Browse Source

Fix constant evaluation of atan2 intrinsic (#1981)

We were evaluating it as atan(y/x), which is incorrect. Note that the atan2 code in HLOperationLower is correct.
Tristan Labelle 6 years ago
parent
commit
657604586c

+ 2 - 2
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -4177,14 +4177,14 @@ static Value * TryEvalIntrinsic(CallInst *CI, IntrinsicOp intriOp) {
     if (Ty->isDoubleTy()) {
       double dV0 = fpV0->getValueAPF().convertToDouble();
       double dV1 = fpV1->getValueAPF().convertToDouble();
-      Value *atanV = ConstantFP::get(CI->getType(), atan(dV0 / dV1));
+      Value *atanV = ConstantFP::get(CI->getType(), atan2(dV0, dV1));
       CI->replaceAllUsesWith(atanV);
       Result = atanV;
     } else {
       DXASSERT_NOMSG(Ty->isFloatTy());
       float fV0 = fpV0->getValueAPF().convertToFloat();
       float fV1 = fpV1->getValueAPF().convertToFloat();
-      Value *atanV = ConstantFP::get(CI->getType(), atanf(fV0 / fV1));
+      Value *atanV = ConstantFP::get(CI->getType(), atan2f(fV0, fV1));
       CI->replaceAllUsesWith(atanV);
       Result = atanV;
     }

+ 16 - 0
tools/clang/test/CodeGenHLSL/expressions/intrinsics/atan2_const_eval_vs_optims.hlsl

@@ -0,0 +1,16 @@
+// RUN: %dxc -E main -T vs_6_2 %s | FileCheck %s
+
+// Regression test for GitHub #1928, where the result of a constant atan2
+// would vary based on if it was evaluated as a constant expression during codegen
+// or later through operations lowering and constant propagation optimization passes.
+
+float2 main() : OUT
+{
+  float x = -1.0f;
+  float y = 2.0f;
+  return float2(
+    // CHECK: call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float 0x4000468A80000000)
+    atan2(2.0f, -1.0f),
+    // CHECK: call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float 0x4000468A80000000)
+    atan2(y, x));
+}