[InstCombine] avoid crashing in exp2->ldexp
authorSanjay Patel <spatel@rotateright.com>
Fri, 10 Feb 2023 12:03:56 +0000 (07:03 -0500)
committerSanjay Patel <spatel@rotateright.com>
Fri, 10 Feb 2023 12:35:39 +0000 (07:35 -0500)
We have exp2 math intrinsics in IR, but no ldexp intrinsics
to handle vector types.

A patch for that was proposed in D14327, but it was not completed.

Issue #60605

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
llvm/test/Transforms/InstCombine/exp2-1.ll

index 60b417dcb06268c9b0ba67b7046e114e13411555..d497a9e8f9f001efd150b374edd7049bbe231ba8 100644 (file)
@@ -2217,11 +2217,16 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) {
       hasFloatVersion(M, Name))
     Ret = optimizeUnaryDoubleFP(CI, B, TLI, true);
 
+  // Bail out for vectors because the code below only expects scalars.
+  // TODO: This could be allowed if we had a ldexp intrinsic (D14327).
   Type *Ty = CI->getType();
-  Value *Op = CI->getArgOperand(0);
+  if (Ty->isVectorTy())
+    return Ret;
 
   // exp2(sitofp(x)) -> ldexp(1.0, sext(x))  if sizeof(x) <= IntSize
   // exp2(uitofp(x)) -> ldexp(1.0, zext(x))  if sizeof(x) < IntSize
+  // TODO: This does not propagate FMF.
+  Value *Op = CI->getArgOperand(0);
   if ((isa<SIToFPInst>(Op) || isa<UIToFPInst>(Op)) &&
       hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) {
     if (Value *Exp = getIntToFPVal(Op, B, TLI->getIntSize()))
index 471f036a2ea3961192b0009688ae5e6b84793167..92a06ee5185fa6c9fa4b473798d2b7656f193569 100644 (file)
@@ -302,3 +302,32 @@ define float @sitofp_scalar_intrinsic_with_FMF(i8 %x) {
   %r = call nnan float @llvm.exp2.f32(float %s)
   ret float %r
 }
+
+; PR60605
+; This would crash because there is no ldexp intrinsic.
+
+define <2 x float> @sitofp_vector_intrinsic_with_FMF(<2 x i8> %x) {
+; LDEXP32-LABEL: @sitofp_vector_intrinsic_with_FMF(
+; LDEXP32-NEXT:    [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
+; LDEXP32-NEXT:    [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
+; LDEXP32-NEXT:    ret <2 x float> [[R]]
+;
+; LDEXP16-LABEL: @sitofp_vector_intrinsic_with_FMF(
+; LDEXP16-NEXT:    [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
+; LDEXP16-NEXT:    [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
+; LDEXP16-NEXT:    ret <2 x float> [[R]]
+;
+; NOLDEXPF-LABEL: @sitofp_vector_intrinsic_with_FMF(
+; NOLDEXPF-NEXT:    [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
+; NOLDEXPF-NEXT:    [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
+; NOLDEXPF-NEXT:    ret <2 x float> [[R]]
+;
+; NOLDEXP-LABEL: @sitofp_vector_intrinsic_with_FMF(
+; NOLDEXP-NEXT:    [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
+; NOLDEXP-NEXT:    [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
+; NOLDEXP-NEXT:    ret <2 x float> [[R]]
+;
+  %s = sitofp <2 x i8> %x to <2 x float>
+  %r = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> %s)
+  ret <2 x float> %r
+}