From e85a300a77cf66921e949a4cf595eba52c637198 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 6 Jul 2018 15:18:58 +0000 Subject: [PATCH] [Constants] extend getBinOpIdentity(); NFC The enhanced version will be used in D48893 and related patches and an almost identical (fadd is different) version is proposed in D28907, so adding this as a preliminary step. llvm-svn: 336444 --- llvm/include/llvm/IR/Constants.h | 13 +++++--- llvm/lib/IR/Constants.cpp | 65 +++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index b6394f5..f9d5ebc 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -1018,10 +1018,15 @@ public: return getLShr(C1, C2, true); } - /// Return the identity for the given binary operation, - /// i.e. a constant C such that X op C = X and C op X = X for every X. It - /// returns null if the operator doesn't have an identity. - static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty); + /// Return the identity constant for a binary opcode. + /// The identity constant C is defined as X op C = X and C op X = X for every + /// X when the binary operation is commutative. If the binop is not + /// commutative, callers can acquire the operand 1 identity constant by + /// setting AllowRHSConstant to true. For example, any shift has a zero + /// identity constant for operand 1: X shift 0 = X. + /// Return nullptr if the operator does not have an identity constant. + static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty, + bool AllowRHSConstant = false); /// 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 diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 032793e..2351e7e 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2271,32 +2271,49 @@ Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2, bool isExact) { isExact ? PossiblyExactOperator::IsExact : 0); } -// FIXME: Add a parameter to specify the operand number for non-commutative ops. -// For example, the operand 1 identity constant for any shift is the null value -// because shift-by-0 always returns operand 0. -Constant *ConstantExpr::getBinOpIdentity(unsigned Opcode, Type *Ty) { - switch (Opcode) { - default: - // Doesn't have an identity. - return nullptr; - - case Instruction::Add: - case Instruction::Or: - case Instruction::Xor: - return Constant::getNullValue(Ty); - - case Instruction::Mul: - return ConstantInt::get(Ty, 1); - - case Instruction::And: - return Constant::getAllOnesValue(Ty); +Constant *ConstantExpr::getBinOpIdentity(unsigned Opcode, Type *Ty, + bool AllowRHSConstant) { + assert(Instruction::isBinaryOp(Opcode) && "Only binops allowed"); + + // Commutative opcodes: it does not matter if AllowRHSConstant is set. + if (Instruction::isCommutative(Opcode)) { + switch (Opcode) { + case Instruction::Add: // X + 0 = X + case Instruction::Or: // X | 0 = X + case Instruction::Xor: // X ^ 0 = X + return Constant::getNullValue(Ty); + case Instruction::Mul: // X * 1 = X + return ConstantInt::get(Ty, 1); + case Instruction::And: // X & -1 = X + return Constant::getAllOnesValue(Ty); + case Instruction::FAdd: // X + -0.0 = X + // TODO: If the fadd has 'nsz', should we return +0.0? + return ConstantFP::getNegativeZero(Ty); + case Instruction::FMul: // X * 1.0 = X + return ConstantFP::get(Ty, 1.0); + default: + llvm_unreachable("Every commutative binop has an identity constant"); + } + } - // TODO: If the fadd has 'nsz', should we return +0.0? - case Instruction::FAdd: - return ConstantFP::getNegativeZero(Ty); + // Non-commutative opcodes: AllowRHSConstant must be set. + if (!AllowRHSConstant) + return nullptr; - case Instruction::FMul: - return ConstantFP::get(Ty, 1.0); + switch (Opcode) { + case Instruction::Sub: // X - 0 = X + case Instruction::Shl: // X << 0 = X + case Instruction::LShr: // X >>u 0 = X + case Instruction::AShr: // X >> 0 = X + case Instruction::FSub: // X - 0.0 = X + return Constant::getNullValue(Ty); + case Instruction::SDiv: // X / 1 = X + case Instruction::UDiv: // X /u 1 = X + return ConstantInt::get(Ty, 1); + case Instruction::FDiv: // X / 1.0 = X + return ConstantFP::get(Ty, 1.0); + default: + return nullptr; } } -- 2.7.4