Skip to content

Commit

Permalink
[IRBuilder] Migrate all binops to folding API
Browse files Browse the repository at this point in the history
Migrate all binops to use FoldXYZ rather than CreateXYZ APIs,
which are compatible with InstSimplifyFolder and fallible constant
folding.

Rather than continuing to add one method for every single operator,
add a generic FoldBinOp (plus variants for nowrap, exact and fmf
operators), which we would need anyway for CreateBinaryOp.

This change is not NFC because IRBuilder with InstSimplifyFolder
may perform more folding. However, this patch changes SCEVExpander
to not use the folder in InsertBinOp to minimize practical impact
and keep this change as close to NFC as possible.
  • Loading branch information
nikic committed Jun 30, 2022
1 parent 8e9360d commit f34dcf2
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 428 deletions.
80 changes: 12 additions & 68 deletions llvm/include/llvm/Analysis/InstSimplifyFolder.h
Expand Up @@ -46,33 +46,25 @@ class InstSimplifyFolder final : public IRBuilderFolder {
// Return an existing value or a constant if the operation can be simplified.
// Otherwise return nullptr.
//===--------------------------------------------------------------------===//
Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false,
bool HasNSW = false) const override {
return simplifyAddInst(LHS, RHS, HasNUW, HasNSW, SQ);
}

Value *FoldAnd(Value *LHS, Value *RHS) const override {
return simplifyAndInst(LHS, RHS, SQ);
}

Value *FoldOr(Value *LHS, Value *RHS) const override {
return simplifyOrInst(LHS, RHS, SQ);
Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS,
Value *RHS) const override {
return simplifyBinOp(Opc, LHS, RHS, SQ);
}

Value *FoldUDiv(Value *LHS, Value *RHS, bool IsExact) const override {
return simplifyUDivInst(LHS, RHS, SQ);
Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
bool IsExact) const override {
return simplifyBinOp(Opc, LHS, RHS, SQ);
}

Value *FoldSDiv(Value *LHS, Value *RHS, bool IsExact) const override {
return simplifySDivInst(LHS, RHS, SQ);
Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
bool HasNUW, bool HasNSW) const override {
return simplifyBinOp(Opc, LHS, RHS, SQ);
}

Value *FoldURem(Value *LHS, Value *RHS) const override {
return simplifyURemInst(LHS, RHS, SQ);
}

Value *FoldSRem(Value *LHS, Value *RHS) const override {
return simplifySRemInst(LHS, RHS, SQ);
Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
FastMathFlags FMF) const override {
return simplifyBinOp(Opc, LHS, RHS, FMF, SQ);
}

Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
Expand Down Expand Up @@ -115,54 +107,6 @@ class InstSimplifyFolder final : public IRBuilderFolder {
return simplifyShuffleVectorInst(V1, V2, Mask, RetTy, SQ);
}

//===--------------------------------------------------------------------===//
// Binary Operators
//===--------------------------------------------------------------------===//

Value *CreateFAdd(Constant *LHS, Constant *RHS) const override {
return ConstFolder.CreateFAdd(LHS, RHS);
}
Value *CreateSub(Constant *LHS, Constant *RHS, bool HasNUW = false,
bool HasNSW = false) const override {
return ConstFolder.CreateSub(LHS, RHS, HasNUW, HasNSW);
}
Value *CreateFSub(Constant *LHS, Constant *RHS) const override {
return ConstFolder.CreateFSub(LHS, RHS);
}
Value *CreateMul(Constant *LHS, Constant *RHS, bool HasNUW = false,
bool HasNSW = false) const override {
return ConstFolder.CreateMul(LHS, RHS, HasNUW, HasNSW);
}
Value *CreateFMul(Constant *LHS, Constant *RHS) const override {
return ConstFolder.CreateFMul(LHS, RHS);
}
Value *CreateFDiv(Constant *LHS, Constant *RHS) const override {
return ConstFolder.CreateFDiv(LHS, RHS);
}
Value *CreateFRem(Constant *LHS, Constant *RHS) const override {
return ConstFolder.CreateFRem(LHS, RHS);
}
Value *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false,
bool HasNSW = false) const override {
return ConstFolder.CreateShl(LHS, RHS, HasNUW, HasNSW);
}
Value *CreateLShr(Constant *LHS, Constant *RHS,
bool isExact = false) const override {
return ConstFolder.CreateLShr(LHS, RHS, isExact);
}
Value *CreateAShr(Constant *LHS, Constant *RHS,
bool isExact = false) const override {
return ConstFolder.CreateAShr(LHS, RHS, isExact);
}
Value *CreateXor(Constant *LHS, Constant *RHS) const override {
return ConstFolder.CreateXor(LHS, RHS);
}

Value *CreateBinOp(Instruction::BinaryOps Opc, Constant *LHS,
Constant *RHS) const override {
return ConstFolder.CreateBinOp(Opc, LHS, RHS);
}

//===--------------------------------------------------------------------===//
// Unary Operators
//===--------------------------------------------------------------------===//
Expand Down
107 changes: 21 additions & 86 deletions llvm/include/llvm/Analysis/TargetFolder.h
Expand Up @@ -22,6 +22,7 @@
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilderFolder.h"
#include "llvm/IR/Operator.h"

namespace llvm {

Expand Down Expand Up @@ -49,63 +50,45 @@ class TargetFolder final : public IRBuilderFolder {
// Return an existing value or a constant if the operation can be simplified.
// Otherwise return nullptr.
//===--------------------------------------------------------------------===//
Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false,
bool HasNSW = false) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC)
return Fold(ConstantExpr::getAdd(LC, RC, HasNUW, HasNSW));
return nullptr;
}

Value *FoldAnd(Value *LHS, Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC)
return Fold(ConstantExpr::getAnd(LC, RC));
return nullptr;
}

Value *FoldOr(Value *LHS, Value *RHS) const override {
Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS,
Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC)
return Fold(ConstantExpr::getOr(LC, RC));
return Fold(ConstantExpr::get(Opc, LC, RC));
return nullptr;
}

Value *FoldUDiv(Value *LHS, Value *RHS, bool IsExact) const override {
Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
bool IsExact) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC)
return Fold(ConstantExpr::getUDiv(LC, RC, IsExact));
return Fold(ConstantExpr::get(
Opc, LC, RC, IsExact ? PossiblyExactOperator::IsExact : 0));
return nullptr;
}

Value *FoldSDiv(Value *LHS, Value *RHS, bool IsExact) const override {
Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
bool HasNUW, bool HasNSW) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC)
return Fold(ConstantExpr::getSDiv(LC, RC, IsExact));
return nullptr;
}

Value *FoldURem(Value *LHS, Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC)
return Fold(ConstantExpr::getURem(LC, RC));
if (LC && RC) {
unsigned Flags = 0;
if (HasNUW)
Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
if (HasNSW)
Flags |= OverflowingBinaryOperator::NoSignedWrap;
return Fold(ConstantExpr::get(Opc, LC, RC, Flags));
}
return nullptr;
}

Value *FoldSRem(Value *LHS, Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC)
return Fold(ConstantExpr::getSRem(LC, RC));
return nullptr;
Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
FastMathFlags FMF) const override {
return FoldBinOp(Opc, LHS, RHS);
}

Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
Expand Down Expand Up @@ -181,54 +164,6 @@ class TargetFolder final : public IRBuilderFolder {
return nullptr;
}

//===--------------------------------------------------------------------===//
// Binary Operators
//===--------------------------------------------------------------------===//

Constant *CreateFAdd(Constant *LHS, Constant *RHS) const override {
return Fold(ConstantExpr::getFAdd(LHS, RHS));
}
Constant *CreateSub(Constant *LHS, Constant *RHS,
bool HasNUW = false, bool HasNSW = false) const override {
return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW));
}
Constant *CreateFSub(Constant *LHS, Constant *RHS) const override {
return Fold(ConstantExpr::getFSub(LHS, RHS));
}
Constant *CreateMul(Constant *LHS, Constant *RHS,
bool HasNUW = false, bool HasNSW = false) const override {
return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW));
}
Constant *CreateFMul(Constant *LHS, Constant *RHS) const override {
return Fold(ConstantExpr::getFMul(LHS, RHS));
}
Constant *CreateFDiv(Constant *LHS, Constant *RHS) const override {
return Fold(ConstantExpr::getFDiv(LHS, RHS));
}
Constant *CreateFRem(Constant *LHS, Constant *RHS) const override {
return Fold(ConstantExpr::getFRem(LHS, RHS));
}
Constant *CreateShl(Constant *LHS, Constant *RHS,
bool HasNUW = false, bool HasNSW = false) const override {
return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW));
}
Constant *CreateLShr(Constant *LHS, Constant *RHS,
bool isExact = false) const override {
return Fold(ConstantExpr::getLShr(LHS, RHS, isExact));
}
Constant *CreateAShr(Constant *LHS, Constant *RHS,
bool isExact = false) const override {
return Fold(ConstantExpr::getAShr(LHS, RHS, isExact));
}
Constant *CreateXor(Constant *LHS, Constant *RHS) const override {
return Fold(ConstantExpr::getXor(LHS, RHS));
}

Constant *CreateBinOp(Instruction::BinaryOps Opc,
Constant *LHS, Constant *RHS) const override {
return Fold(ConstantExpr::get(Opc, LHS, RHS));
}

//===--------------------------------------------------------------------===//
// Unary Operators
//===--------------------------------------------------------------------===//
Expand Down

0 comments on commit f34dcf2

Please sign in to comment.