54#include "llvm/IR/IntrinsicsS390.h"
82 std::vector<BinaryOperator *> LogicOpsWorklist;
84 std::set<Instruction *> PossibleJunk;
99 ConvertedInsts[
I] = std::make_tuple(V, Mask, Worthy);
100 auto &
M = *
I->getFunction()->getParent();
101 auto &Ctx =
M.getContext();
102 for (
auto *U :
I->users()) {
103 auto *LI = dyn_cast<BinaryOperator>(U);
105 (LI->getOpcode() == Instruction::And ||
106 LI->getOpcode() == Instruction::Or ||
107 LI->getOpcode() == Instruction::Xor)) {
108 LogicOpsWorklist.push_back(LI);
116char SystemZTDCPass::ID = 0;
118 "SystemZ Test Data Class optimization",
false,
false)
121 return new SystemZTDCPass();
124void SystemZTDCPass::convertFCmp(
CmpInst &
I) {
125 Value *Op0 =
I.getOperand(0);
126 auto *
Const = dyn_cast<ConstantFP>(
I.getOperand(1));
127 auto Pred =
I.getPredicate();
134 APFloat NegSmallest = Smallest;
138 if (
Const->isZero()) {
141 }
else if (
Const->isInfinity()) {
143 WhichConst =
Const->isNegative() ? 2 : 1;
144 }
else if (
Const->isExactlyValue(Smallest)) {
150 }
else if (
Const->isExactlyValue(NegSmallest)) {
161 static const int Masks[][4] = {
208 Mask |= Masks[WhichConst][0];
210 Mask |= Masks[WhichConst][1];
212 Mask |= Masks[WhichConst][2];
214 Mask |= Masks[WhichConst][3];
218 if (
CallInst *CI = dyn_cast<CallInst>(Op0)) {
220 if (
F &&
F->getIntrinsicID() == Intrinsic::fabs) {
224 Op0 = CI->getArgOperand(0);
227 Worthy = WhichConst != 0;
228 PossibleJunk.insert(CI);
231 converted(&
I, Op0, Mask, Worthy);
234void SystemZTDCPass::convertICmp(
CmpInst &
I) {
235 Value *Op0 =
I.getOperand(0);
236 auto *
Const = dyn_cast<ConstantInt>(
I.getOperand(1));
237 auto Pred =
I.getPredicate();
241 if (
auto *Cast = dyn_cast<BitCastInst>(Op0)) {
243 if (!Cast->getSrcTy()->isFloatTy() &&
244 !Cast->getSrcTy()->isDoubleTy() &&
245 !Cast->getSrcTy()->isFP128Ty())
247 Value *
V = Cast->getOperand(0);
259 PossibleJunk.insert(Cast);
260 converted(&
I, V, Mask,
true);
261 }
else if (
auto *CI = dyn_cast<CallInst>(Op0)) {
264 if (!
F ||
F->getIntrinsicID() != Intrinsic::s390_tdc)
266 if (!
Const->isZero())
268 Value *
V = CI->getArgOperand(0);
269 auto *MaskC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
273 int Mask = MaskC->getZExtValue();
284 PossibleJunk.insert(CI);
285 converted(&
I, V, Mask,
false);
292 bool Worthy0, Worthy1;
293 std::tie(Op0, Mask0, Worthy0) = ConvertedInsts[cast<Instruction>(
I.getOperand(0))];
294 std::tie(Op1, Mask1, Worthy1) = ConvertedInsts[cast<Instruction>(
I.getOperand(1))];
298 switch (
I.getOpcode()) {
299 case Instruction::And:
300 Mask = Mask0 & Mask1;
302 case Instruction::Or:
303 Mask = Mask0 | Mask1;
305 case Instruction::Xor:
306 Mask = Mask0 ^ Mask1;
311 converted(&
I, Op0, Mask,
true);
314bool SystemZTDCPass::runOnFunction(
Function &
F) {
315 auto &TPC = getAnalysis<TargetPassConfig>();
321 ConvertedInsts.
clear();
322 LogicOpsWorklist.clear();
323 PossibleJunk.clear();
327 if (
I.getOpcode() == Instruction::FCmp)
328 convertFCmp(cast<CmpInst>(
I));
329 else if (
I.getOpcode() == Instruction::ICmp)
330 convertICmp(cast<CmpInst>(
I));
334 if (ConvertedInsts.
empty())
338 while (!LogicOpsWorklist.empty()) {
340 LogicOpsWorklist.pop_back();
343 if (ConvertedInsts.
count(dyn_cast<Instruction>(
Op->getOperand(0))) &&
344 ConvertedInsts.
count(dyn_cast<Instruction>(
Op->getOperand(1))) &&
353 auto &Ctx =
M.getContext();
355 bool MadeChange =
false;
356 for (
auto &It :
reverse(ConvertedInsts)) {
361 std::tie(V, Mask, Worthy) = It.second;
362 if (!
I->user_empty()) {
370 IRB.CreateIntrinsic(Intrinsic::s390_tdc,
V->getType(), {V, MaskVal});
372 I->replaceAllUsesWith(ICmp);
375 I->eraseFromParent();
384 for (
auto *
I : PossibleJunk)
386 I->eraseFromParent();
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
This file implements a map that provides insertion order iteration.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Target-Independent Code Generator Pass Configuration Options pass.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
This class represents a function call, abstracting a target machine's calling convention.
This class is the base class for the comparison instructions.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_SGT
signed greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This class implements a map that also provides access to all stored values in a deterministic order.
size_type count(const KeyT &Key) const
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Primary interface to the complete machine description for the target machine.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
Target-Independent Code Generator Pass Configuration Options.
const fltSemantics & getFltSemantics() const
static IntegerType * getInt1Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
const unsigned TDCMASK_NEGATIVE
const unsigned TDCMASK_NORMAL_MINUS
const unsigned TDCMASK_MINUS
const unsigned TDCMASK_SUBNORMAL_MINUS
const unsigned TDCMASK_ZERO
const unsigned TDCMASK_NORMAL_PLUS
const unsigned TDCMASK_ALL
const unsigned TDCMASK_SUBNORMAL_PLUS
const unsigned TDCMASK_INFINITY_PLUS
const unsigned TDCMASK_POSITIVE
const unsigned TDCMASK_INFINITY_MINUS
const unsigned TDCMASK_NAN
const unsigned TDCMASK_PLUS
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
FunctionPass * createSystemZTDCPass()
void initializeSystemZTDCPassPass(PassRegistry &)