[llvm] [ConstantFold][RFC] Refactor getBinOpAbsorber function (PR #109736)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 26 19:10:26 PDT 2024
https://github.com/eric-xtang1008 updated https://github.com/llvm/llvm-project/pull/109736
>From 2fcc0080d2d712663edfd6bc6909f84b0a75fb3d Mon Sep 17 00:00:00 2001
From: "eric.tang" <eric.tang at starfivetech.com>
Date: Mon, 23 Sep 2024 10:27:59 +0800
Subject: [PATCH] [ConstantFold][RFC] Refactor getBinOpAbsorber function
Add a AllowLHSConstant parameter in getBinOpAbsorber fuction for
supporting more Binary operators.
Signed-off-by: eric.tang <eric.tang at starfivetech.com>
---
llvm/include/llvm/IR/Constants.h | 7 +++++--
llvm/lib/IR/ConstantFold.cpp | 34 ++++++++++----------------------
llvm/lib/IR/Constants.cpp | 29 +++++++++++++++++++++------
3 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 3b16aa039a5087..15b90589b7e2b5 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -1210,8 +1210,11 @@ class ConstantExpr : public Constant {
/// Return the absorbing element for the given binary
/// operation, i.e. a constant C such that X op C = C and C op X = C for
/// every X. For example, this returns zero for integer multiplication.
- /// It returns null if the operator doesn't have an absorbing element.
- static Constant *getBinOpAbsorber(unsigned Opcode, Type *Ty);
+ /// If AllowLHSConstant is true, the LHS operand is a constant C that must be
+ /// defined as C op X = C. It returns null if the operator doesn't have
+ /// an absorbing element.
+ static Constant *getBinOpAbsorber(unsigned Opcode, Type *Ty,
+ bool AllowLHSConstant = false);
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 05ab0968ef6f39..573e1fbc5ea892 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -729,13 +729,16 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
// Neither constant should be UndefValue, unless these are vector constants.
assert((!HasScalarUndefOrScalableVectorUndef) && "Unexpected UndefValue");
+ Constant *Absorber = ConstantExpr::getBinOpAbsorber(
+ Opcode, C1->getType(), /*AllowLHSConstant*/ true);
+
+ // Handle absorbing element when the Opcode is a commutative opcode
+ if ((C1 == Absorber || C2 == Absorber) && Instruction::isCommutative(Opcode))
+ return Absorber;
+
// Handle simplifications when the RHS is a constant int.
if (ConstantInt *CI2 = dyn_cast<ConstantInt>(C2)) {
switch (Opcode) {
- case Instruction::Mul:
- if (CI2->isZero())
- return C2; // X * 0 == 0
- break;
case Instruction::UDiv:
case Instruction::SDiv:
if (CI2->isZero())
@@ -749,9 +752,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
return PoisonValue::get(CI2->getType()); // X % 0 == poison
break;
case Instruction::And:
- if (CI2->isZero())
- return C2; // X & 0 == 0
-
+ assert(!CI2->isZero() && "And zero handled above");
if (ConstantExpr *CE1 = dyn_cast<ConstantExpr>(C1)) {
// If and'ing the address of a global with a constant, fold it.
if (CE1->getOpcode() == Instruction::PtrToInt &&
@@ -791,10 +792,6 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
}
}
break;
- case Instruction::Or:
- if (CI2->isMinusOne())
- return C2; // X | -1 == -1
- break;
}
} else if (isa<ConstantInt>(C1)) {
// If C1 is a ConstantInt and C2 is not, swap the operands.
@@ -854,19 +851,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
}
}
- switch (Opcode) {
- case Instruction::SDiv:
- case Instruction::UDiv:
- case Instruction::URem:
- case Instruction::SRem:
- case Instruction::LShr:
- case Instruction::AShr:
- case Instruction::Shl:
- if (CI1->isZero()) return C1;
- break;
- default:
- break;
- }
+ if (C1 == Absorber)
+ return C1;
} else if (ConstantFP *CFP1 = dyn_cast<ConstantFP>(C1)) {
if (ConstantFP *CFP2 = dyn_cast<ConstantFP>(C2)) {
const APFloat &C1V = CFP1->getValueAPF();
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index d6c00a4b547829..fe3a086c5772de 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -2735,17 +2735,34 @@ Constant *ConstantExpr::getIdentity(Instruction *I, Type *Ty,
return nullptr;
}
-Constant *ConstantExpr::getBinOpAbsorber(unsigned Opcode, Type *Ty) {
+Constant *ConstantExpr::getBinOpAbsorber(unsigned Opcode, Type *Ty,
+ bool AllowLHSConstant) {
switch (Opcode) {
default:
- // Doesn't have an absorber.
- return nullptr;
+ break;
- case Instruction::Or:
+ case Instruction::Or: // -1 | X = -1
return Constant::getAllOnesValue(Ty);
- case Instruction::And:
- case Instruction::Mul:
+ case Instruction::And: // 0 & X = 0
+ case Instruction::Mul: // 0 * X = 0
+ return Constant::getNullValue(Ty);
+ }
+
+ // AllowLHSConstant must be set.
+ if (!AllowLHSConstant)
+ return nullptr;
+
+ switch (Opcode) {
+ default:
+ return nullptr;
+ case Instruction::Shl: // 0 << X = 0
+ case Instruction::LShr: // 0 >>l X = 0
+ case Instruction::AShr: // 0 >>a X = 0
+ case Instruction::SDiv: // 0 /s X = 0
+ case Instruction::UDiv: // 0 /u X = 0
+ case Instruction::URem: // 0 %u X = 0
+ case Instruction::SRem: // 0 %s X = 0
return Constant::getNullValue(Ty);
}
}
More information about the llvm-commits
mailing list