Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

134 lines
3.5 KiB
C++

#include "WebAssembly.h"
#include "WebAssemblySubtarget.h"
#include "WebAssemblyTargetMachine.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Pass.h"
using namespace llvm;
using namespace llvm::PatternMatch;
namespace {
struct WebAssemblyReduceToAnyAllTrue final : FunctionPass {
static char ID;
WebAssemblyTargetMachine &TM;
const Module *CachedModule = nullptr;
bool ModuleHasInterestingIntrinsics = false;
WebAssemblyReduceToAnyAllTrue(WebAssemblyTargetMachine &TM)
: FunctionPass(ID), TM(TM) {}
StringRef getPassName() const override {
return "WebAssembly convert reduce to any_true/all_true";
}
bool hasInterestingIntrinsics(const Module &M) {
if (CachedModule == &M)
return ModuleHasInterestingIntrinsics;
CachedModule = &M;
ModuleHasInterestingIntrinsics = false;
for (const Function &Fn : M.functions()) {
switch (Fn.getIntrinsicID()) {
case Intrinsic::vector_reduce_or:
case Intrinsic::vector_reduce_and:
ModuleHasInterestingIntrinsics = true;
return true;
default:
break;
}
}
return false;
}
bool runOnFunction(Function &F) override {
if (!TM.getSubtarget<WebAssemblySubtarget>(F).hasSIMD128())
return false;
if (!hasInterestingIntrinsics(*F.getParent()))
return false;
bool Changed = false;
for (auto &BB : F) {
for (auto It = BB.begin(), E = BB.end(); It != E;) {
Instruction *I = &*It++;
auto *Cmp = dyn_cast<ICmpInst>(I);
if (!Cmp || Cmp->getPredicate() != ICmpInst::ICMP_NE)
continue;
Value *Reduce = nullptr;
if (!match(Cmp, m_ICmp(m_Value(Reduce), m_ZeroInt())))
continue;
auto *II = dyn_cast<IntrinsicInst>(Reduce);
if (!II || !II->hasOneUse())
continue;
IRBuilder<> B(Cmp);
Value *Vec = II->getArgOperand(0);
Module *M = F.getParent();
auto makeIntrinsic = [&](Intrinsic::ID ID, Value *Arg) {
Function *Fn =
Intrinsic::getOrInsertDeclaration(M, ID, {Arg->getType()});
return B.CreateCall(Fn, {Arg});
};
Value *New = nullptr;
switch (II->getIntrinsicID()) {
case Intrinsic::vector_reduce_or: {
// reduce.or(X) != 0 -> anytrue(X)
Value *Any = makeIntrinsic(Intrinsic::wasm_anytrue, Vec);
New = B.CreateICmpNE(Any, ConstantInt::get(Any->getType(), 0));
break;
}
case Intrinsic::vector_reduce_and: {
// reduce.and(zext (icmp ne X, zeroinitializer)) != 0 -> alltrue(X)
// Match: zext (icmp ne X, 0) from <N x i1> to <N x iX>
CmpPredicate Pred;
Value *LHS = nullptr;
if (!match(Vec, m_ZExt(m_c_ICmp(Pred, m_Value(LHS), m_Zero()))))
continue;
if (Pred != ICmpInst::ICMP_NE)
continue;
Value *All = makeIntrinsic(Intrinsic::wasm_alltrue, LHS);
New = B.CreateICmpNE(All, ConstantInt::get(All->getType(), 0));
break;
}
default:
continue;
}
Cmp->replaceAllUsesWith(New);
Cmp->eraseFromParent();
if (II->use_empty())
II->eraseFromParent();
Changed = true;
}
}
return Changed;
}
};
} // end anonymous namespace
char WebAssemblyReduceToAnyAllTrue::ID = 0;
FunctionPass *
llvm::createWebAssemblyReduceToAnyAllTrue(WebAssemblyTargetMachine &TM) {
return new WebAssemblyReduceToAnyAllTrue(TM);
}