Skip to content

Commit

Permalink
[FPEnv] EarlyCSE support for constrained intrinsics, default FP envir…
Browse files Browse the repository at this point in the history
…onment edition

EarlyCSE cannot distinguish between floating point instructions and
constrained floating point intrinsics that are marked as running in the
default FP environment. Said intrinsics are supposed to behave exactly the
same as the regular FP instructions. Teach EarlyCSE to handle them in that
case.

Differential Revision: https://reviews.llvm.org/D99962
  • Loading branch information
kpneal committed May 20, 2021
1 parent f4ccbaf commit f21f1ee
Show file tree
Hide file tree
Showing 4 changed files with 369 additions and 5 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/IntrinsicInst.h
Expand Up @@ -432,6 +432,7 @@ class ConstrainedFPIntrinsic : public IntrinsicInst {
bool isTernaryOp() const;
Optional<RoundingMode> getRoundingMode() const;
Optional<fp::ExceptionBehavior> getExceptionBehavior() const;
bool isDefaultFPEnvironment() const;

// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I);
Expand Down
28 changes: 24 additions & 4 deletions llvm/lib/IR/IntrinsicInst.cpp
Expand Up @@ -172,8 +172,10 @@ Value *InstrProfIncrementInst::getStep() const {

Optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
unsigned NumOperands = getNumArgOperands();
Metadata *MD =
cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
Metadata *MD = nullptr;
auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2));
if (MAV)
MD = MAV->getMetadata();
if (!MD || !isa<MDString>(MD))
return None;
return StrToRoundingMode(cast<MDString>(MD)->getString());
Expand All @@ -182,13 +184,31 @@ Optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
Optional<fp::ExceptionBehavior>
ConstrainedFPIntrinsic::getExceptionBehavior() const {
unsigned NumOperands = getNumArgOperands();
Metadata *MD =
cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
Metadata *MD = nullptr;
auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1));
if (MAV)
MD = MAV->getMetadata();
if (!MD || !isa<MDString>(MD))
return None;
return StrToExceptionBehavior(cast<MDString>(MD)->getString());
}

bool ConstrainedFPIntrinsic::isDefaultFPEnvironment() const {
Optional<fp::ExceptionBehavior> Except = getExceptionBehavior();
if (Except) {
if (Except.getValue() != fp::ebIgnore)
return false;
}

Optional<RoundingMode> Rounding = getRoundingMode();
if (Rounding) {
if (Rounding.getValue() != RoundingMode::NearestTiesToEven)
return false;
}

return true;
}

FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
Metadata *MD = cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
if (!MD || !isa<MDString>(MD))
Expand Down
23 changes: 22 additions & 1 deletion llvm/lib/Transforms/Scalar/EarlyCSE.cpp
Expand Up @@ -108,8 +108,29 @@ struct SimpleValue {

static bool canHandle(Instruction *Inst) {
// This can only handle non-void readnone functions.
if (CallInst *CI = dyn_cast<CallInst>(Inst))
// Also handled are constrained intrinsic that look like the types
// of instruction handled below (UnaryOperator, etc.).
if (CallInst *CI = dyn_cast<CallInst>(Inst)) {
if (Function *F = CI->getCalledFunction()) {
switch ((Intrinsic::ID)F->getIntrinsicID()) {
case Intrinsic::experimental_constrained_fadd:
case Intrinsic::experimental_constrained_fsub:
case Intrinsic::experimental_constrained_fmul:
case Intrinsic::experimental_constrained_fdiv:
case Intrinsic::experimental_constrained_frem:
case Intrinsic::experimental_constrained_fptosi:
case Intrinsic::experimental_constrained_sitofp:
case Intrinsic::experimental_constrained_fptoui:
case Intrinsic::experimental_constrained_uitofp:
case Intrinsic::experimental_constrained_fcmp:
case Intrinsic::experimental_constrained_fcmps: {
auto *CFP = cast<ConstrainedFPIntrinsic>(CI);
return CFP->isDefaultFPEnvironment();
}
}
}
return CI->doesNotAccessMemory() && !CI->getType()->isVoidTy();
}
return isa<CastInst>(Inst) || isa<UnaryOperator>(Inst) ||
isa<BinaryOperator>(Inst) || isa<GetElementPtrInst>(Inst) ||
isa<CmpInst>(Inst) || isa<SelectInst>(Inst) ||
Expand Down

0 comments on commit f21f1ee

Please sign in to comment.