annotate lib/Target/SystemZ/SystemZTDC.cpp @ 131:f476a9ba4795

http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
author mir3636
date Fri, 16 Feb 2018 21:02:11 +0900
parents 803732b1fca8
children c2174574ed3a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
120
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
1 //===-- SystemZTDC.cpp - Utilize Test Data Class instruction --------------===//
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
2 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
3 // The LLVM Compiler Infrastructure
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
4 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
5 // This file is distributed under the University of Illinois Open Source
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
6 // License. See LICENSE.TXT for details.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
7 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
8 //===----------------------------------------------------------------------===//
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
9 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
10 // This pass looks for instructions that can be replaced by a Test Data Class
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
11 // instruction, and replaces them when profitable.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
12 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
13 // Roughly, the following rules are recognized:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
14 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
15 // 1: fcmp pred X, 0 -> tdc X, mask
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
16 // 2: fcmp pred X, +-inf -> tdc X, mask
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
17 // 3: fcmp pred X, +-minnorm -> tdc X, mask
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
18 // 4: tdc (fabs X), mask -> tdc X, newmask
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
19 // 5: icmp slt (bitcast float X to int), 0 -> tdc X, mask [ie. signbit]
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
20 // 6: icmp sgt (bitcast float X to int), -1 -> tdc X, mask
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
21 // 7: icmp ne/eq (call @llvm.s390.tdc.*(X, mask)) -> tdc X, mask/~mask
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
22 // 8: and i1 (tdc X, M1), (tdc X, M2) -> tdc X, (M1 & M2)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
23 // 9: or i1 (tdc X, M1), (tdc X, M2) -> tdc X, (M1 | M2)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
24 // 10: xor i1 (tdc X, M1), (tdc X, M2) -> tdc X, (M1 ^ M2)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
25 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
26 // The pass works in 4 steps:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
27 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
28 // 1. All fcmp and icmp instructions in a function are checked for a match
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
29 // with rules 1-3 and 5-7. Their TDC equivalents are stored in
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
30 // the ConvertedInsts mapping. If the operand of a fcmp instruction is
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
31 // a fabs, it's also folded according to rule 4.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
32 // 2. All and/or/xor i1 instructions whose both operands have been already
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
33 // mapped are mapped according to rules 8-10. LogicOpsWorklist is used
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
34 // as a queue of instructions to check.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
35 // 3. All mapped instructions that are considered worthy of conversion (ie.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
36 // replacing them will actually simplify the final code) are replaced
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
37 // with a call to the s390.tdc intrinsic.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
38 // 4. All intermediate results of replaced instructions are removed if unused.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
39 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
40 // Instructions that match rules 1-3 are considered unworthy of conversion
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
41 // on their own (since a comparison instruction is superior), but are mapped
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
42 // in the hopes of folding the result using rules 4 and 8-10 (likely removing
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
43 // the original comparison in the process).
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
44 //
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
45 //===----------------------------------------------------------------------===//
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
46
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
47 #include "SystemZ.h"
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
48 #include "llvm/ADT/MapVector.h"
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
49 #include "llvm/IR/Constants.h"
121
803732b1fca8 LLVM 5.0
kono
parents: 120
diff changeset
50 #include "llvm/IR/IRBuilder.h"
120
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
51 #include "llvm/IR/InstIterator.h"
121
803732b1fca8 LLVM 5.0
kono
parents: 120
diff changeset
52 #include "llvm/IR/Instructions.h"
120
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
53 #include "llvm/IR/IntrinsicInst.h"
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
54 #include "llvm/IR/LegacyPassManager.h"
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
55 #include "llvm/IR/Module.h"
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
56 #include <deque>
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
57 #include <set>
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
58
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
59 using namespace llvm;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
60
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
61 namespace llvm {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
62 void initializeSystemZTDCPassPass(PassRegistry&);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
63 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
64
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
65 namespace {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
66
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
67 class SystemZTDCPass : public FunctionPass {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
68 public:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
69 static char ID;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
70 SystemZTDCPass() : FunctionPass(ID) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
71 initializeSystemZTDCPassPass(*PassRegistry::getPassRegistry());
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
72 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
73
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
74 bool runOnFunction(Function &F) override;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
75 private:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
76 // Maps seen instructions that can be mapped to a TDC, values are
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
77 // (TDC operand, TDC mask, worthy flag) triples.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
78 MapVector<Instruction *, std::tuple<Value *, int, bool>> ConvertedInsts;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
79 // The queue of and/or/xor i1 instructions to be potentially folded.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
80 std::vector<BinaryOperator *> LogicOpsWorklist;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
81 // Instructions matched while folding, to be removed at the end if unused.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
82 std::set<Instruction *> PossibleJunk;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
83
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
84 // Tries to convert a fcmp instruction.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
85 void convertFCmp(CmpInst &I);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
86
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
87 // Tries to convert an icmp instruction.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
88 void convertICmp(CmpInst &I);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
89
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
90 // Tries to convert an i1 and/or/xor instruction, whose both operands
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
91 // have been already converted.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
92 void convertLogicOp(BinaryOperator &I);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
93
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
94 // Marks an instruction as converted - adds it to ConvertedInsts and adds
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
95 // any and/or/xor i1 users to the queue.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
96 void converted(Instruction *I, Value *V, int Mask, bool Worthy) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
97 ConvertedInsts[I] = std::make_tuple(V, Mask, Worthy);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
98 auto &M = *I->getFunction()->getParent();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
99 auto &Ctx = M.getContext();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
100 for (auto *U : I->users()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
101 auto *LI = dyn_cast<BinaryOperator>(U);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
102 if (LI && LI->getType() == Type::getInt1Ty(Ctx) &&
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
103 (LI->getOpcode() == Instruction::And ||
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
104 LI->getOpcode() == Instruction::Or ||
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
105 LI->getOpcode() == Instruction::Xor)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
106 LogicOpsWorklist.push_back(LI);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
107 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
108 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
109 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
110 };
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
111
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
112 } // end anonymous namespace
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
113
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
114 char SystemZTDCPass::ID = 0;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
115 INITIALIZE_PASS(SystemZTDCPass, "systemz-tdc",
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
116 "SystemZ Test Data Class optimization", false, false)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
117
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
118 FunctionPass *llvm::createSystemZTDCPass() {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
119 return new SystemZTDCPass();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
120 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
121
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
122 void SystemZTDCPass::convertFCmp(CmpInst &I) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
123 Value *Op0 = I.getOperand(0);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
124 auto *Const = dyn_cast<ConstantFP>(I.getOperand(1));
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
125 auto Pred = I.getPredicate();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
126 // Only comparisons with consts are interesting.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
127 if (!Const)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
128 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
129 // Compute the smallest normal number (and its negation).
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
130 auto &Sem = Op0->getType()->getFltSemantics();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
131 APFloat Smallest = APFloat::getSmallestNormalized(Sem);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
132 APFloat NegSmallest = Smallest;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
133 NegSmallest.changeSign();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
134 // Check if Const is one of our recognized consts.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
135 int WhichConst;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
136 if (Const->isZero()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
137 // All comparisons with 0 can be converted.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
138 WhichConst = 0;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
139 } else if (Const->isInfinity()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
140 // Likewise for infinities.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
141 WhichConst = Const->isNegative() ? 2 : 1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
142 } else if (Const->isExactlyValue(Smallest)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
143 // For Smallest, we cannot do EQ separately from GT.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
144 if ((Pred & CmpInst::FCMP_OGE) != CmpInst::FCMP_OGE &&
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
145 (Pred & CmpInst::FCMP_OGE) != 0)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
146 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
147 WhichConst = 3;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
148 } else if (Const->isExactlyValue(NegSmallest)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
149 // Likewise for NegSmallest, we cannot do EQ separately from LT.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
150 if ((Pred & CmpInst::FCMP_OLE) != CmpInst::FCMP_OLE &&
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
151 (Pred & CmpInst::FCMP_OLE) != 0)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
152 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
153 WhichConst = 4;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
154 } else {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
155 // Not one of our special constants.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
156 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
157 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
158 // Partial masks to use for EQ, GT, LT, UN comparisons, respectively.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
159 static const int Masks[][4] = {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
160 { // 0
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
161 SystemZ::TDCMASK_ZERO, // eq
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
162 SystemZ::TDCMASK_POSITIVE, // gt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
163 SystemZ::TDCMASK_NEGATIVE, // lt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
164 SystemZ::TDCMASK_NAN, // un
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
165 },
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
166 { // inf
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
167 SystemZ::TDCMASK_INFINITY_PLUS, // eq
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
168 0, // gt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
169 (SystemZ::TDCMASK_ZERO |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
170 SystemZ::TDCMASK_NEGATIVE |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
171 SystemZ::TDCMASK_NORMAL_PLUS |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
172 SystemZ::TDCMASK_SUBNORMAL_PLUS), // lt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
173 SystemZ::TDCMASK_NAN, // un
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
174 },
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
175 { // -inf
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
176 SystemZ::TDCMASK_INFINITY_MINUS, // eq
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
177 (SystemZ::TDCMASK_ZERO |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
178 SystemZ::TDCMASK_POSITIVE |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
179 SystemZ::TDCMASK_NORMAL_MINUS |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
180 SystemZ::TDCMASK_SUBNORMAL_MINUS), // gt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
181 0, // lt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
182 SystemZ::TDCMASK_NAN, // un
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
183 },
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
184 { // minnorm
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
185 0, // eq (unsupported)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
186 (SystemZ::TDCMASK_NORMAL_PLUS |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
187 SystemZ::TDCMASK_INFINITY_PLUS), // gt (actually ge)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
188 (SystemZ::TDCMASK_ZERO |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
189 SystemZ::TDCMASK_NEGATIVE |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
190 SystemZ::TDCMASK_SUBNORMAL_PLUS), // lt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
191 SystemZ::TDCMASK_NAN, // un
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
192 },
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
193 { // -minnorm
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
194 0, // eq (unsupported)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
195 (SystemZ::TDCMASK_ZERO |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
196 SystemZ::TDCMASK_POSITIVE |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
197 SystemZ::TDCMASK_SUBNORMAL_MINUS), // gt
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
198 (SystemZ::TDCMASK_NORMAL_MINUS |
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
199 SystemZ::TDCMASK_INFINITY_MINUS), // lt (actually le)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
200 SystemZ::TDCMASK_NAN, // un
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
201 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
202 };
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
203 // Construct the mask as a combination of the partial masks.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
204 int Mask = 0;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
205 if (Pred & CmpInst::FCMP_OEQ)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
206 Mask |= Masks[WhichConst][0];
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
207 if (Pred & CmpInst::FCMP_OGT)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
208 Mask |= Masks[WhichConst][1];
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
209 if (Pred & CmpInst::FCMP_OLT)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
210 Mask |= Masks[WhichConst][2];
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
211 if (Pred & CmpInst::FCMP_UNO)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
212 Mask |= Masks[WhichConst][3];
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
213 // A lone fcmp is unworthy of tdc conversion on its own, but may become
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
214 // worthy if combined with fabs.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
215 bool Worthy = false;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
216 if (CallInst *CI = dyn_cast<CallInst>(Op0)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
217 Function *F = CI->getCalledFunction();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
218 if (F && F->getIntrinsicID() == Intrinsic::fabs) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
219 // Fold with fabs - adjust the mask appropriately.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
220 Mask &= SystemZ::TDCMASK_PLUS;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
221 Mask |= Mask >> 1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
222 Op0 = CI->getArgOperand(0);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
223 // A combination of fcmp with fabs is a win, unless the constant
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
224 // involved is 0 (which is handled by later passes).
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
225 Worthy = WhichConst != 0;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
226 PossibleJunk.insert(CI);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
227 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
228 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
229 converted(&I, Op0, Mask, Worthy);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
230 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
231
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
232 void SystemZTDCPass::convertICmp(CmpInst &I) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
233 Value *Op0 = I.getOperand(0);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
234 auto *Const = dyn_cast<ConstantInt>(I.getOperand(1));
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
235 auto Pred = I.getPredicate();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
236 // All our icmp rules involve comparisons with consts.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
237 if (!Const)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
238 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
239 if (auto *Cast = dyn_cast<BitCastInst>(Op0)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
240 // Check for icmp+bitcast used for signbit.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
241 if (!Cast->getSrcTy()->isFloatTy() &&
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
242 !Cast->getSrcTy()->isDoubleTy() &&
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
243 !Cast->getSrcTy()->isFP128Ty())
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
244 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
245 Value *V = Cast->getOperand(0);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
246 int Mask;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
247 if (Pred == CmpInst::ICMP_SLT && Const->isZero()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
248 // icmp slt (bitcast X), 0 - set if sign bit true
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
249 Mask = SystemZ::TDCMASK_MINUS;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
250 } else if (Pred == CmpInst::ICMP_SGT && Const->isMinusOne()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
251 // icmp sgt (bitcast X), -1 - set if sign bit false
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
252 Mask = SystemZ::TDCMASK_PLUS;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
253 } else {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
254 // Not a sign bit check.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
255 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
256 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
257 PossibleJunk.insert(Cast);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
258 converted(&I, V, Mask, true);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
259 } else if (auto *CI = dyn_cast<CallInst>(Op0)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
260 // Check if this is a pre-existing call of our tdc intrinsic.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
261 Function *F = CI->getCalledFunction();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
262 if (!F || F->getIntrinsicID() != Intrinsic::s390_tdc)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
263 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
264 if (!Const->isZero())
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
265 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
266 Value *V = CI->getArgOperand(0);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
267 auto *MaskC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
268 // Bail if the mask is not a constant.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
269 if (!MaskC)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
270 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
271 int Mask = MaskC->getZExtValue();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
272 Mask &= SystemZ::TDCMASK_ALL;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
273 if (Pred == CmpInst::ICMP_NE) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
274 // icmp ne (call llvm.s390.tdc(...)), 0 -> simple TDC
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
275 } else if (Pred == CmpInst::ICMP_EQ) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
276 // icmp eq (call llvm.s390.tdc(...)), 0 -> TDC with inverted mask
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
277 Mask ^= SystemZ::TDCMASK_ALL;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
278 } else {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
279 // An unknown comparison - ignore.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
280 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
281 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
282 PossibleJunk.insert(CI);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
283 converted(&I, V, Mask, false);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
284 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
285 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
286
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
287 void SystemZTDCPass::convertLogicOp(BinaryOperator &I) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
288 Value *Op0, *Op1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
289 int Mask0, Mask1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
290 bool Worthy0, Worthy1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
291 std::tie(Op0, Mask0, Worthy0) = ConvertedInsts[cast<Instruction>(I.getOperand(0))];
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
292 std::tie(Op1, Mask1, Worthy1) = ConvertedInsts[cast<Instruction>(I.getOperand(1))];
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
293 if (Op0 != Op1)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
294 return;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
295 int Mask;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
296 switch (I.getOpcode()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
297 case Instruction::And:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
298 Mask = Mask0 & Mask1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
299 break;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
300 case Instruction::Or:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
301 Mask = Mask0 | Mask1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
302 break;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
303 case Instruction::Xor:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
304 Mask = Mask0 ^ Mask1;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
305 break;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
306 default:
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
307 llvm_unreachable("Unknown op in convertLogicOp");
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
308 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
309 converted(&I, Op0, Mask, true);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
310 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
311
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
312 bool SystemZTDCPass::runOnFunction(Function &F) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
313 ConvertedInsts.clear();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
314 LogicOpsWorklist.clear();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
315 PossibleJunk.clear();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
316
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
317 // Look for icmp+fcmp instructions.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
318 for (auto &I : instructions(F)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
319 if (I.getOpcode() == Instruction::FCmp)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
320 convertFCmp(cast<CmpInst>(I));
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
321 else if (I.getOpcode() == Instruction::ICmp)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
322 convertICmp(cast<CmpInst>(I));
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
323 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
324
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
325 // If none found, bail already.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
326 if (ConvertedInsts.empty())
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
327 return false;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
328
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
329 // Process the queue of logic instructions.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
330 while (!LogicOpsWorklist.empty()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
331 BinaryOperator *Op = LogicOpsWorklist.back();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
332 LogicOpsWorklist.pop_back();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
333 // If both operands mapped, and the instruction itself not yet mapped,
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
334 // convert it.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
335 if (ConvertedInsts.count(dyn_cast<Instruction>(Op->getOperand(0))) &&
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
336 ConvertedInsts.count(dyn_cast<Instruction>(Op->getOperand(1))) &&
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
337 !ConvertedInsts.count(Op))
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
338 convertLogicOp(*Op);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
339 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
340
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
341 // Time to actually replace the instructions. Do it in the reverse order
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
342 // of finding them, since there's a good chance the earlier ones will be
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
343 // unused (due to being folded into later ones).
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
344 Module &M = *F.getParent();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
345 auto &Ctx = M.getContext();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
346 Value *Zero32 = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
347 bool MadeChange = false;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
348 for (auto &It : reverse(ConvertedInsts)) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
349 Instruction *I = It.first;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
350 Value *V;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
351 int Mask;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
352 bool Worthy;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
353 std::tie(V, Mask, Worthy) = It.second;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
354 if (!I->user_empty()) {
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
355 // If used and unworthy of conversion, skip it.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
356 if (!Worthy)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
357 continue;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
358 // Call the intrinsic, compare result with 0.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
359 Value *TDCFunc = Intrinsic::getDeclaration(&M, Intrinsic::s390_tdc,
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
360 V->getType());
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
361 IRBuilder<> IRB(I);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
362 Value *MaskVal = ConstantInt::get(Type::getInt64Ty(Ctx), Mask);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
363 Instruction *TDC = IRB.CreateCall(TDCFunc, {V, MaskVal});
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
364 Value *ICmp = IRB.CreateICmp(CmpInst::ICMP_NE, TDC, Zero32);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
365 I->replaceAllUsesWith(ICmp);
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
366 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
367 // If unused, or used and converted, remove it.
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
368 I->eraseFromParent();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
369 MadeChange = true;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
370 }
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
371
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
372 if (!MadeChange)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
373 return false;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
374
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
375 // We've actually done something - now clear misc accumulated junk (fabs,
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
376 // bitcast).
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
377 for (auto *I : PossibleJunk)
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
378 if (I->user_empty())
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
379 I->eraseFromParent();
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
380
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
381 return true;
1172e4bd9c6f update 4.0.0
mir3636
parents:
diff changeset
382 }