[InstCombine] canonicalize fneg with llvm.sin

This is a follow-up to rL339604 which did the same transform
for a sin libcall. The handling of intrinsics vs. libcalls
is unfortunately scattered, so I'm just adding this next to
the existing transform for llvm.cos for now.

This should resolve PR38458:
https://bugs.llvm.org/show_bug.cgi?id=38458
If the call was already negated, the negates will cancel
each other out.

llvm-svn: 340952
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 2993f00..4755e85 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2124,16 +2124,25 @@
   }
   case Intrinsic::cos:
   case Intrinsic::amdgcn_cos: {
-    Value *SrcSrc;
+    Value *X;
     Value *Src = II->getArgOperand(0);
-    if (match(Src, m_FNeg(m_Value(SrcSrc))) ||
-        match(Src, m_FAbs(m_Value(SrcSrc)))) {
+    if (match(Src, m_FNeg(m_Value(X))) || match(Src, m_FAbs(m_Value(X)))) {
       // cos(-x) -> cos(x)
       // cos(fabs(x)) -> cos(x)
-      II->setArgOperand(0, SrcSrc);
+      II->setArgOperand(0, X);
       return II;
     }
-
+    break;
+  }
+  case Intrinsic::sin: {
+    Value *X;
+    if (match(II->getArgOperand(0), m_OneUse(m_FNeg(m_Value(X))))) {
+      // sin(-x) --> -sin(x)
+      Value *NewSin = Builder.CreateIntrinsic(Intrinsic::sin, { X }, II);
+      Instruction *FNeg = BinaryOperator::CreateFNeg(NewSin);
+      FNeg->copyFastMathFlags(II);
+      return FNeg;
+    }
     break;
   }
   case Intrinsic::ppc_altivec_lvx:
diff --git a/llvm/test/Transforms/InstCombine/cos-sin-intrinsic.ll b/llvm/test/Transforms/InstCombine/cos-sin-intrinsic.ll
index 98c2434..ef5513d 100644
--- a/llvm/test/Transforms/InstCombine/cos-sin-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/cos-sin-intrinsic.ll
@@ -92,14 +92,14 @@
   ret <2 x float> %cos
 }
 
-; TODO: Negate is canonicalized after sin.
+; Negate is canonicalized after sin.
 
 declare <2 x float> @llvm.sin.v2f32(<2 x float>)
 
 define <2 x float> @fneg_sin(<2 x float> %x){
 ; CHECK-LABEL: @fneg_sin(
-; CHECK-NEXT:    [[NEGX:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = call <2 x float> @llvm.sin.v2f32(<2 x float> [[NEGX]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.sin.v2f32(<2 x float> [[X:%.*]])
+; CHECK-NEXT:    [[R:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %negx = fsub <2 x float> <float -0.0, float -0.0>, %x
@@ -107,12 +107,12 @@
   ret <2 x float> %r
 }
 
-; TODO: FMF are not required, but they should propagate.
+; FMF are not required, but they should propagate.
 
 define <2 x float> @fneg_sin_fmf(<2 x float> %x){
 ; CHECK-LABEL: @fneg_sin_fmf(
-; CHECK-NEXT:    [[NEGX:%.*]] = fsub fast <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = call nnan arcp afn <2 x float> @llvm.sin.v2f32(<2 x float> [[NEGX]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call nnan arcp afn <2 x float> @llvm.sin.v2f32(<2 x float> [[X:%.*]])
+; CHECK-NEXT:    [[R:%.*]] = fsub nnan arcp afn <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]]
 ; CHECK-NEXT:    ret <2 x float> [[R]]
 ;
   %negx = fsub fast <2 x float> <float -0.0, float -0.0>, %x