[llvm] [VPlan] Introduce VPlanConstantFolder (PR #125365)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sat May 3 05:15:52 PDT 2025


================
@@ -0,0 +1,157 @@
+//===- VPlanConstantFolder.h - ConstantFolder for VPlan -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANCONSTANTFOLDER_H
+#define LLVM_TRANSFORMS_VECTORIZE_VPLANCONSTANTFOLDER_H
+
+#include "VPlan.h"
+#include "VPlanValue.h"
+#include "llvm/Analysis/TargetFolder.h"
+
+namespace llvm {
+class VPConstantFolder {
+  TargetFolder Folder;
+  VPTypeAnalysis TypeInfo;
+
+  Constant *getIRConstant(VPValue *V) const {
+    if (!V->isLiveIn())
+      return nullptr;
+    return dyn_cast_if_present<Constant>(V->getLiveInIRValue());
+  }
+
+  Value *foldBinOp(Instruction::BinaryOps Opcode, VPValue *LHS,
+                   VPValue *RHS) const {
+    auto *LC = getIRConstant(LHS);
+    auto *RC = getIRConstant(RHS);
+    if (LC && RC)
+      return Folder.FoldBinOp(Opcode, LC, RC);
+    return nullptr;
+  }
+
+  Value *foldNot(VPValue *Op) const {
+    auto *C = getIRConstant(Op);
+    if (C)
+      return Folder.FoldBinOp(Instruction::BinaryOps::Xor, C,
+                              Constant::getAllOnesValue(C->getType()));
+    return nullptr;
+  }
+
+  Value *foldLogicalAnd(VPValue *LHS, VPValue *RHS) const {
+    auto *LC = getIRConstant(LHS);
+    auto *RC = getIRConstant(RHS);
+    if (LC && RC)
+      return Folder.FoldSelect(LC, RC,
+                               ConstantInt::getNullValue(RC->getType()));
+    return nullptr;
+  }
+
+  Value *foldSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal) const {
+    auto *CC = getIRConstant(Cond);
+    auto *TV = getIRConstant(TrueVal);
+    auto *FV = getIRConstant(FalseVal);
+    if (CC && TV && FV)
+      return Folder.FoldSelect(CC, TV, FV);
+    return nullptr;
+  }
+
+  Value *foldCmp(CmpInst::Predicate Pred, VPValue *LHS, VPValue *RHS) const {
+    auto *LC = getIRConstant(LHS);
+    auto *RC = getIRConstant(RHS);
+    if (LC && RC)
+      return Folder.FoldCmp(Pred, LC, RC);
+    return nullptr;
+  }
+
+  Value *foldGEP(Type *Ty, VPValue *Base, ArrayRef<VPValue *> Offsets,
+                 GEPNoWrapFlags NW) const {
+    auto *BC = getIRConstant(Base);
+    if (!BC)
+      return nullptr;
+    SmallVector<Value *> IdxList;
+    for (auto *O : Offsets) {
+      if (auto *OffsetV = getIRConstant(O))
+        IdxList.emplace_back(OffsetV);
+      else
+        return nullptr;
+    }
+    return Folder.FoldGEP(Ty, BC, IdxList, NW);
+  }
+
+  Value *foldInsertElement(VPValue *Vec, VPValue *NewElt, VPValue *Idx) const {
+    auto *VC = getIRConstant(Vec);
+    auto *EC = getIRConstant(NewElt);
+    auto *IC = getIRConstant(Idx);
+    if (VC && EC && IC)
+      Folder.FoldInsertElement(VC, EC, IC);
+    return nullptr;
+  }
+
+  Value *foldExtractElement(VPValue *Vec, VPValue *Idx) const {
+    auto *VC = getIRConstant(Vec);
+    auto *IC = getIRConstant(Idx);
+    if (VC && IC)
+      Folder.FoldExtractElement(VC, IC);
+    return nullptr;
+  }
+
+  Value *foldCast(Instruction::CastOps Opcode, VPValue *Op,
+                  Type *DestTy) const {
+    auto *C = getIRConstant(Op);
+    if (C)
+      return Folder.FoldCast(Opcode, C, DestTy);
+    return nullptr;
+  }
+
+public:
+  VPConstantFolder(const DataLayout &DL, const VPTypeAnalysis &TypeInfo)
+      : Folder(DL), TypeInfo(TypeInfo) {}
+
+  Value *tryToConstantFold(VPRecipeBase &R, unsigned Opcode,
+                           ArrayRef<VPValue *> Ops) {
----------------
fhahn wrote:

Would it simplify things to check front check if any op is not a live in and do getIRConstant  in a single place?

https://github.com/llvm/llvm-project/pull/125365


More information about the llvm-commits mailing list