brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 79272fe Raw
192 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ReduceOperands.h"10#include "llvm/IR/Constants.h"11#include "llvm/IR/InstIterator.h"12#include "llvm/IR/InstrTypes.h"13#include "llvm/IR/Operator.h"14#include "llvm/IR/PatternMatch.h"15#include "llvm/IR/Type.h"16 17using namespace llvm;18using namespace PatternMatch;19 20static void21extractOperandsFromModule(Oracle &O, ReducerWorkItem &WorkItem,22                          function_ref<Value *(Use &)> ReduceValue) {23  Module &Program = WorkItem.getModule();24 25  for (auto &F : Program.functions()) {26    for (auto &I : instructions(&F)) {27      if (PHINode *Phi = dyn_cast<PHINode>(&I)) {28        for (auto &Op : Phi->incoming_values()) {29          if (Value *Reduced = ReduceValue(Op)) {30            if (!O.shouldKeep())31              Phi->setIncomingValueForBlock(Phi->getIncomingBlock(Op), Reduced);32          }33        }34 35        continue;36      }37 38      for (auto &Op : I.operands()) {39        if (Value *Reduced = ReduceValue(Op)) {40          if (!O.shouldKeep())41            Op.set(Reduced);42        }43      }44    }45  }46}47 48static bool isOne(Use &Op) {49  auto *C = dyn_cast<Constant>(Op);50  return C && C->isOneValue();51}52 53static bool isZero(Use &Op) {54  auto *C = dyn_cast<Constant>(Op);55  return C && C->isNullValue();56}57 58static bool isZeroOrOneFP(Value *Op) {59  const APFloat *C;60  return match(Op, m_APFloat(C)) &&61         ((C->isZero() && !C->isNegative()) || C->isExactlyValue(1.0));62}63 64static bool shouldReduceOperand(Use &Op) {65  Type *Ty = Op->getType();66  if (Ty->isLabelTy() || Ty->isMetadataTy())67    return false;68  // TODO: be more precise about which GEP operands we can reduce (e.g. array69  // indexes)70  if (isa<GEPOperator>(Op.getUser()))71    return false;72  if (auto *CB = dyn_cast<CallBase>(Op.getUser())) {73    if (&CB->getCalledOperandUse() == &Op)74      return false;75  }76  // lifetime intrinsic argument must be an alloca.77  if (isa<LifetimeIntrinsic>(Op.getUser()))78    return false;79  return true;80}81 82static bool switchCaseExists(Use &Op, ConstantInt *CI) {83  SwitchInst *SI = dyn_cast<SwitchInst>(Op.getUser());84  if (!SI)85    return false;86  return SI->findCaseValue(CI) != SI->case_default();87}88 89void llvm::reduceOperandsOneDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {90  auto ReduceValue = [](Use &Op) -> Value * {91    if (!shouldReduceOperand(Op))92      return nullptr;93 94    Type *Ty = Op->getType();95    if (auto *IntTy = dyn_cast<IntegerType>(Ty)) {96      // Don't duplicate an existing switch case.97      if (switchCaseExists(Op, ConstantInt::get(IntTy, 1)))98        return nullptr;99      // Don't replace existing ones and zeroes.100      return (isOne(Op) || isZero(Op)) ? nullptr : ConstantInt::get(IntTy, 1);101    }102 103    if (Ty->isFloatingPointTy())104      return isZeroOrOneFP(Op) ? nullptr : ConstantFP::get(Ty, 1.0);105 106    if (VectorType *VT = dyn_cast<VectorType>(Ty)) {107      if (isOne(Op) || isZero(Op) || isZeroOrOneFP(Op))108        return nullptr;109 110      Type *ElementType = VT->getElementType();111      Constant *C;112      if (ElementType->isFloatingPointTy()) {113        C = ConstantFP::get(ElementType, 1.0);114      } else if (IntegerType *IntTy = dyn_cast<IntegerType>(ElementType)) {115        C = ConstantInt::get(IntTy, 1);116      } else {117        return nullptr;118      }119      return ConstantVector::getSplat(VT->getElementCount(), C);120    }121 122    return nullptr;123  };124  extractOperandsFromModule(O, WorkItem, ReduceValue);125}126 127void llvm::reduceOperandsZeroDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {128  auto ReduceValue = [](Use &Op) -> Value * {129    if (!shouldReduceOperand(Op))130      return nullptr;131 132    // Avoid introducing 0-sized allocations.133    if (isa<AllocaInst>(Op.getUser()))134      return nullptr;135 136    // Don't duplicate an existing switch case.137    if (auto *IntTy = dyn_cast<IntegerType>(Op->getType()))138      if (switchCaseExists(Op, ConstantInt::get(IntTy, 0)))139        return nullptr;140 141    if (auto *TET = dyn_cast<TargetExtType>(Op->getType())) {142      if (isa<ConstantTargetNone, PoisonValue>(Op))143        return nullptr;144      if (TET->hasProperty(TargetExtType::HasZeroInit))145        return ConstantTargetNone::get(TET);146      return nullptr;147    }148 149    // Don't replace existing zeroes.150    return isZero(Op) ? nullptr : Constant::getNullValue(Op->getType());151  };152  extractOperandsFromModule(O, WorkItem, ReduceValue);153}154 155void llvm::reduceOperandsNaNDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {156  auto ReduceValue = [](Use &Op) -> Value * {157    Type *Ty = Op->getType();158    if (!Ty->isFPOrFPVectorTy())159      return nullptr;160 161    // Prefer 0.0 or 1.0 over NaN.162    //163    // TODO: Preferring NaN may make more sense because FP operations are more164    // universally foldable.165    if (match(Op.get(), m_NaN()) || isZeroOrOneFP(Op.get()))166      return nullptr;167 168    if (VectorType *VT = dyn_cast<VectorType>(Ty)) {169      return ConstantVector::getSplat(VT->getElementCount(),170                                      ConstantFP::getQNaN(VT->getElementType()));171    }172 173    return ConstantFP::getQNaN(Ty);174  };175  extractOperandsFromModule(O, WorkItem, ReduceValue);176}177 178void llvm::reduceOperandsPoisonDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {179  auto ReduceValue = [](Use &Op) -> Value * {180    Type *Ty = Op->getType();181    if (auto *TET = dyn_cast<TargetExtType>(Ty)) {182      if (isa<ConstantTargetNone, PoisonValue>(Op))183        return nullptr;184      return PoisonValue::get(TET);185    }186 187    return nullptr;188  };189 190  extractOperandsFromModule(O, WorkItem, ReduceValue);191}192