//===-- SystemZTDC.cpp - Utilize Test Data Class instruction --------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This pass looks for instructions that can be replaced by a Test Data Class // instruction, and replaces them when profitable. // // Roughly, the following rules are recognized: // // 1: fcmp pred X, 0 -> tdc X, mask // 2: fcmp pred X, +-inf -> tdc X, mask // 3: fcmp pred X, +-minnorm -> tdc X, mask // 4: tdc (fabs X), mask -> tdc X, newmask // 5: icmp slt (bitcast float X to int), 0 -> tdc X, mask [ie. signbit] // 6: icmp sgt (bitcast float X to int), -1 -> tdc X, mask // 7: icmp ne/eq (call @llvm.s390.tdc.*(X, mask)) -> tdc X, mask/~mask // 8: and i1 (tdc X, M1), (tdc X, M2) -> tdc X, (M1 & M2) // 9: or i1 (tdc X, M1), (tdc X, M2) -> tdc X, (M1 | M2) // 10: xor i1 (tdc X, M1), (tdc X, M2) -> tdc X, (M1 ^ M2) // // The pass works in 4 steps: // // 1. All fcmp and icmp instructions in a function are checked for a match // with rules 1-3 and 5-7. Their TDC equivalents are stored in // the ConvertedInsts mapping. If the operand of a fcmp instruction is // a fabs, it's also folded according to rule 4. // 2. All and/or/xor i1 instructions whose both operands have been already // mapped are mapped according to rules 8-10. LogicOpsWorklist is used // as a queue of instructions to check. // 3. All mapped instructions that are considered worthy of conversion (ie. // replacing them will actually simplify the final code) are replaced // with a call to the s390.tdc intrinsic. // 4. All intermediate results of replaced instructions are removed if unused. // // Instructions that match rules 1-3 are considered unworthy of conversion // on their own (since a comparison instruction is superior), but are mapped // in the hopes of folding the result using rules 4 and 8-10 (likely removing // the original comparison in the process). // //===----------------------------------------------------------------------===// #include "SystemZ.h" #include "SystemZSubtarget.h" #include "llvm/ADT/MapVector.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicsS390.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Target/TargetMachine.h" #include <deque> #include <set> usingnamespacellvm; namespace { class SystemZTDCPass : public FunctionPass { … }; } // end anonymous namespace char SystemZTDCPass::ID = …; INITIALIZE_PASS(…) FunctionPass *llvm::createSystemZTDCPass() { … } void SystemZTDCPass::convertFCmp(CmpInst &I) { … } void SystemZTDCPass::convertICmp(CmpInst &I) { … } void SystemZTDCPass::convertLogicOp(BinaryOperator &I) { … } bool SystemZTDCPass::runOnFunction(Function &F) { … }