Skip to content

PreISelIntrinsicLowering: Lower llvm.exp/llvm.exp2 to a loop if scalable vec arg #117568

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 24, 2025

Conversation

steplong
Copy link
Contributor

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Nov 25, 2024

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Stephen Long (steplong)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/117568.diff

2 Files Affected:

  • (modified) llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp (+57)
  • (added) llvm/test/Transforms/PreISelIntrinsicLowering/expand-exp.ll (+23)
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
index 4a3d1673c2a7c1..74f54e43a8386f 100644
--- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -335,6 +335,59 @@ bool PreISelIntrinsicLowering::expandMemIntrinsicUses(Function &F) const {
   return Changed;
 }
 
+static bool lowerExpIntrinsicToLoop(Module &M, Function &F, CallInst *CI) {
+  ScalableVectorType *ScalableTy =
+      dyn_cast<ScalableVectorType>(F.getArg(0)->getType());
+  if (!ScalableTy) {
+    return false;
+  }
+
+  BasicBlock *PreLoopBB = CI->getParent();
+  BasicBlock *PostLoopBB = nullptr;
+  Function *ParentFunc = PreLoopBB->getParent();
+  LLVMContext &Ctx = PreLoopBB->getContext();
+
+  PostLoopBB = PreLoopBB->splitBasicBlock(CI);
+  BasicBlock *LoopBB = BasicBlock::Create(Ctx, "", ParentFunc, PostLoopBB);
+  PreLoopBB->getTerminator()->setSuccessor(0, LoopBB);
+
+  // loop preheader
+  IRBuilder<> PreLoopBuilder(PreLoopBB->getTerminator());
+  Value *VScale = PreLoopBuilder.CreateVScale(
+      ConstantInt::get(PreLoopBuilder.getInt64Ty(), 1));
+  Value *N = ConstantInt::get(PreLoopBuilder.getInt64Ty(),
+                              ScalableTy->getMinNumElements());
+  Value *LoopEnd = PreLoopBuilder.CreateMul(VScale, N);
+
+  // loop body
+  IRBuilder<> LoopBuilder(LoopBB);
+  Type *Int64Ty = LoopBuilder.getInt64Ty();
+
+  PHINode *LoopIndex = LoopBuilder.CreatePHI(Int64Ty, 2);
+  LoopIndex->addIncoming(ConstantInt::get(Int64Ty, 0U), PreLoopBB);
+  PHINode *Vec = LoopBuilder.CreatePHI(ScalableTy, 2);
+  Vec->addIncoming(CI->getArgOperand(0), PreLoopBB);
+
+  Value *Elem = LoopBuilder.CreateExtractElement(Vec, LoopIndex);
+  Function *Exp = Intrinsic::getOrInsertDeclaration(
+      &M, Intrinsic::exp, ScalableTy->getElementType());
+  Value *Res = LoopBuilder.CreateCall(Exp, Elem);
+  Value *NewVec = LoopBuilder.CreateInsertElement(Vec, Res, LoopIndex);
+  Vec->addIncoming(NewVec, LoopBB);
+
+  Value *One = ConstantInt::get(Int64Ty, 1U);
+  Value *NextLoopIndex = LoopBuilder.CreateAdd(LoopIndex, One);
+  LoopIndex->addIncoming(NextLoopIndex, LoopBB);
+
+  Value *ExitCond =
+      LoopBuilder.CreateICmp(CmpInst::ICMP_EQ, NextLoopIndex, LoopEnd);
+  LoopBuilder.CreateCondBr(ExitCond, PostLoopBB, LoopBB);
+
+  CI->replaceAllUsesWith(NewVec);
+  CI->eraseFromParent();
+  return true;
+}
+
 bool PreISelIntrinsicLowering::lowerIntrinsics(Module &M) const {
   bool Changed = false;
   for (Function &F : M) {
@@ -453,6 +506,10 @@ bool PreISelIntrinsicLowering::lowerIntrinsics(Module &M) const {
     case Intrinsic::objc_sync_exit:
       Changed |= lowerObjCCall(F, "objc_sync_exit");
       break;
+    case Intrinsic::exp:
+      Changed |= forEachCall(
+          F, [&](CallInst *CI) { return lowerExpIntrinsicToLoop(M, F, CI); });
+      break;
     }
   }
   return Changed;
diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/expand-exp.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/expand-exp.ll
new file mode 100644
index 00000000000000..6ad181033f233a
--- /dev/null
+++ b/llvm/test/Transforms/PreISelIntrinsicLowering/expand-exp.ll
@@ -0,0 +1,23 @@
+; RUN: opt -passes=pre-isel-intrinsic-lowering -S < %s | FileCheck %s
+
+define <vscale x 4 x float> @softmax_kernel() {
+; CHECK-LABEL: define <vscale x 4 x float> @softmax_kernel(
+; CHECK-NEXT:    [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+; CHECK-NEXT:    [[LOOPEND:%.*]] = mul i64 [[VSCALE]], 4
+; CHECK-NEXT:    br label %[[LOOPBODY:.*]]
+; CHECK:       [[LOOPBODY]]:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i64 [ 0, %0 ], [ [[NEW_IDX:%.*]], %[[LOOPBODY]] ]
+; CHECK-NEXT:    [[VEC:%.*]] = phi <vscale x 4 x float> [ zeroinitializer, %0 ], [ [[NEW_VEC:.*]], %[[LOOPBODY]] ]
+; CHECK-NEXT:    [[ELEM:%.*]] = extractelement <vscale x 4 x float> [[VEC]], i64 [[IDX]]
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.exp.f32(float [[ELEM]])
+; CHECK-NEXT:    [[NEW_VEC:%.*]] = insertelement <vscale x 4 x float> [[VEC]], float [[RES]], i64 [[IDX]]
+; CHECK-NEXT:    [[NEW_IDX]] = add i64 [[IDX]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[NEW_IDX]], [[LOOPEND]]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[LOOPEXIT:.*]], label %[[LOOPBODY]]
+; CHECK:       [[LOOPEXIT]]:
+; CHECK-NEXT:    ret <vscale x 4 x float> [[NEW_VEC]]
+  %1 = call <vscale x 4 x float> @llvm.exp.nxv4f32(<vscale x 4 x float> zeroinitializer)
+  ret <vscale x 4 x float> %1
+}
+
+declare <vscale x 4 x float> @llvm.exp.nxv4f32(<vscale x 4 x float>)

@arsenm arsenm added the SVE ARM Scalable Vector Extensions label Dec 4, 2024
@steplong
Copy link
Contributor Author

steplong commented Dec 6, 2024

@arsenm I added the fixed vector test case, but if we decide to only do this for scalable vectors, then I'll remove it. Let me know how we should do the legality check as I'm new to this.

@steplong steplong changed the title PreISelIntrinsicLowering: Lower llvm.exp to a loop if scalable vec arg PreISelIntrinsicLowering: Lower llvm.exp/llvm.exp2 to a loop if scalable vec arg Dec 18, 2024
@steplong steplong requested a review from arsenm January 7, 2025 15:08
@steplong
Copy link
Contributor Author

steplong commented Jan 13, 2025

Hi, what can be done to get this in? For the fixed vector case, it looks like it's being handled by SelectionDAG, specifically ISD::FEXP is getting expanded in VectorLegalizer::LegalizeOp(llvm::SDValue) (for ARM64)

…ble vec arg

If the argument to the intrinsic call to llvm.exp and llvm.exp2 is a
scalable vector, lower it into a loop in PreISelIntrinsicLowering. If it
is a fixed vector, let SelectionDAG handle it.
@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Jan 23, 2025
Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with nit

@steplong steplong merged commit ab976a1 into llvm:main Jan 24, 2025
8 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 24, 2025

LLVM Buildbot has detected a new failure on builder flang-aarch64-dylib running on linaro-flang-aarch64-dylib while building llvm at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/50/builds/9373

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
842.440 [1999/7/4816] Building CXX object tools/mlir/lib/Dialect/Transform/Transforms/CMakeFiles/obj.MLIRTransformDialectTransforms.dir/CheckUses.cpp.o
842.517 [1999/6/4817] Building CXX object tools/mlir/lib/Analysis/CMakeFiles/obj.MLIRAnalysis.dir/CallGraph.cpp.o
842.542 [1999/5/4818] Building CXX object tools/mlir/lib/Conversion/TosaToArith/CMakeFiles/obj.MLIRTosaToArith.dir/TosaToArith.cpp.o
842.605 [1999/4/4819] Building CXX object tools/mlir/lib/Analysis/CMakeFiles/obj.MLIRAnalysis.dir/AliasAnalysis.cpp.o
842.642 [1999/3/4820] Building CXX object tools/mlir/lib/Analysis/CMakeFiles/obj.MLIRAnalysis.dir/DataLayoutAnalysis.cpp.o
842.687 [1999/2/4821] Building CXX object tools/mlir/lib/Analysis/CMakeFiles/obj.MLIRAnalysis.dir/DataFlowFramework.cpp.o
842.907 [1996/4/4822] Building CXX object tools/mlir/lib/Analysis/CMakeFiles/obj.MLIRAnalysis.dir/Liveness.cpp.o
843.095 [1996/3/4823] Building CXX object tools/mlir/lib/Analysis/CMakeFiles/obj.MLIRAnalysis.dir/FlatLinearValueConstraints.cpp.o
843.103 [1996/2/4824] Building CXX object tools/mlir/lib/Analysis/CMakeFiles/obj.MLIRAnalysis.dir/CFGLoopInfo.cpp.o
855.756 [1996/1/4825] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o
FAILED: tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o 
/usr/local/bin/c++ -DGTEST_HAS_RTTI=0 -DMLIR_INCLUDE_TESTS -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR/../Dialect/Test -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wundef -Werror=mismatched-tags -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o -MF tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o.d -o tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestVisitorsGeneric.cpp
In file included from /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestVisitorsGeneric.cpp:9:
/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test/TestOps.h:148:10: fatal error: 'TestOps.h.inc' file not found
  148 | #include "TestOps.h.inc"
      |          ^~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.

@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 25, 2025

LLVM Buildbot has detected a new failure on builder clang-ppc64-aix running on aix-ppc64 while building llvm at step 3 "clean-build-dir".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/64/builds/2086

Here is the relevant piece of the build log for the reference
Step 3 (clean-build-dir) failure: Delete failed. (failure) (timed out)
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: ClangScanDeps/verbose.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: rm -rf /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
+ rm -rf /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
RUN: at line 2: split-file /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
+ split-file /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
RUN: at line 3: sed -e "s|DIR|/home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp|g" /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json.in > /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json
+ sed -e 's|DIR|/home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp|g' /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json.in
RUN: at line 5: /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/clang-scan-deps -compilation-database /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json -v -o /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/result.json 2>&1 | /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/FileCheck /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test
+ /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/clang-scan-deps -compilation-database /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json -v -o /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/result.json
+ /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/FileCheck /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test
/home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test:6:11: error: CHECK: expected string not found in input
// CHECK: *** Virtual File System Stats:
          ^
<stdin>:1:1: note: scanning from here
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
^
<stdin>:1:8: note: possible intended match here
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
       ^

Input file: <stdin>
Check file: /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test

-dump-input=help explains the following input dump.

Input was:
<<<<<<
           1: PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. 
check:6'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
check:6'1            ?                                                                                                     possible intended match
>>>>>>

--

********************


@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 25, 2025

LLVM Buildbot has detected a new failure on builder lld-x86_64-win running on as-worker-93 while building llvm at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/2158

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM-Unit :: Support/./SupportTests.exe/38/87' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe-LLVM-Unit-9220-38-87.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=87 GTEST_SHARD_INDEX=38 C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe
--

Script:
--
C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe --gtest_filter=ProgramEnvTest.CreateProcessLongPath
--
C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(160): error: Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(163): error: fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied



C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:160
Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:163
fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied




********************


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms SVE ARM Scalable Vector Extensions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants