Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
llvm.7809
backport-llvm-r233688
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File backport-llvm-r233688 of Package llvm.7809
------------------------------------------------------------------------ r233688 | uweigand | 2015-03-31 14:52:27 +0200 (Tue, 31 Mar 2015) | 11 lines [SystemZ] Provide basic TargetTransformInfo implementation This hooks up the TargetTransformInfo machinery for SystemZ, and provides an implementation of getIntImmCost. In addition, the patch adds the isLegalICmpImmediate and isLegalAddImmediate TargetLowering overrides, and updates a couple of test cases where we now generate slightly better code. ------------------------------------------------------------------------ Index: lib/Target/SystemZ/SystemZ.h =================================================================== --- lib/Target/SystemZ/SystemZ.h.orig +++ lib/Target/SystemZ/SystemZ.h @@ -21,6 +21,7 @@ namespace llvm { class SystemZTargetMachine; class FunctionPass; +class ImmutablePass; namespace SystemZ { // Condition-code mask values. @@ -112,6 +113,8 @@ FunctionPass *createSystemZElimComparePa FunctionPass *createSystemZShortenInstPass(SystemZTargetMachine &TM); FunctionPass *createSystemZLongBranchPass(SystemZTargetMachine &TM); FunctionPass *createSystemZLDCleanupPass(SystemZTargetMachine &TM); +ImmutablePass *createSystemZTargetTransformInfoPass( + const SystemZTargetMachine *TM); } // end namespace llvm #endif Index: lib/Target/SystemZ/SystemZISelLowering.h =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.h.orig +++ lib/Target/SystemZ/SystemZISelLowering.h @@ -212,6 +212,8 @@ public: virtual EVT getSetCCResultType(LLVMContext &, EVT) const LLVM_OVERRIDE; virtual bool isFMAFasterThanFMulAndFAdd(EVT VT) const LLVM_OVERRIDE; virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const LLVM_OVERRIDE; + virtual bool isLegalICmpImmediate(int64_t Imm) const LLVM_OVERRIDE; + virtual bool isLegalAddImmediate(int64_t Imm) const LLVM_OVERRIDE; virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const LLVM_OVERRIDE; virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const Index: lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.cpp.orig +++ lib/Target/SystemZ/SystemZISelLowering.cpp @@ -340,6 +340,16 @@ bool SystemZTargetLowering::isFPImmLegal return Imm.isZero() || Imm.isNegZero(); } +bool SystemZTargetLowering::isLegalICmpImmediate(int64_t Imm) const { + // We can use CGFI or CLGFI. + return isInt<32>(Imm) || isUInt<32>(Imm); +} + +bool SystemZTargetLowering::isLegalAddImmediate(int64_t Imm) const { + // We can use ALGFI or SLGFI. + return isUInt<32>(Imm) || isUInt<32>(-Imm); +} + bool SystemZTargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const { // Unaligned accesses should never be slower than the expanded version. Index: lib/Target/SystemZ/SystemZTargetMachine.h =================================================================== --- lib/Target/SystemZ/SystemZTargetMachine.h.orig +++ lib/Target/SystemZ/SystemZTargetMachine.h @@ -67,6 +67,7 @@ public: // Override LLVMTargetMachine virtual TargetPassConfig *createPassConfig(PassManagerBase &PM) LLVM_OVERRIDE; + virtual void addAnalysisPasses(PassManagerBase &PM) LLVM_OVERRIDE; }; } // end namespace llvm Index: lib/Target/SystemZ/SystemZTargetMachine.cpp =================================================================== --- lib/Target/SystemZ/SystemZTargetMachine.cpp.orig +++ lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -9,6 +9,7 @@ #include "SystemZTargetMachine.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/PassManager.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Transforms/Scalar.h" @@ -110,3 +111,12 @@ bool SystemZPassConfig::addPreEmitPass() TargetPassConfig *SystemZTargetMachine::createPassConfig(PassManagerBase &PM) { return new SystemZPassConfig(this, PM); } + +void SystemZTargetMachine::addAnalysisPasses(PassManagerBase &PM) { + // Add first the target-independent BasicTTI pass, then our SystemZ pass. + // This allows the SystemZ pass to delegate to the target independent layer + // when appropriate. + PM.add(createBasicTargetTransformInfoPass(this)); + PM.add(createSystemZTargetTransformInfoPass(this)); +} + Index: lib/Target/SystemZ/CMakeLists.txt =================================================================== --- lib/Target/SystemZ/CMakeLists.txt.orig +++ lib/Target/SystemZ/CMakeLists.txt @@ -29,6 +29,7 @@ add_llvm_target(SystemZCodeGen SystemZShortenInst.cpp SystemZSubtarget.cpp SystemZTargetMachine.cpp + SystemZTargetTransformInfo.cpp ) add_dependencies(LLVMSystemZCodeGen SystemZCommonTableGen intrinsics_gen) Index: lib/Target/SystemZ/SystemZTargetTransformInfo.cpp =================================================================== --- /dev/null +++ lib/Target/SystemZ/SystemZTargetTransformInfo.cpp @@ -0,0 +1,302 @@ +//===-- SystemZTargetTransformInfo.cpp - SystemZ-specific TTI -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a TargetTransformInfo analysis pass specific to the +// SystemZ target machine. It uses the target's detailed information to provide +// more precise answers to certain TTI queries, while letting the target +// independent and default TTI implementations handle the rest. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "systemztti" + +#include "SystemZTargetMachine.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/CostTable.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +// Declare the pass initialization routine locally as target-specific passes +// don't have a target-wide initialization entry point, and so we rely on the +// pass constructor initialization. +namespace llvm { +void initializeSystemZTTIPass(PassRegistry &); +} + +namespace { + +class SystemZTTI : public ImmutablePass, public TargetTransformInfo { + const SystemZSubtarget *ST; + const SystemZTargetLowering *TLI; + const SystemZInstrInfo *TII; + +public: + SystemZTTI() : ImmutablePass(ID), ST(0), TLI(0), TII(0) { + llvm_unreachable("This pass cannot be directly constructed"); + } + + SystemZTTI(const SystemZTargetMachine *TM) + : ImmutablePass(ID), ST(TM->getSubtargetImpl()), + TLI(TM->getTargetLowering()), TII(TM->getInstrInfo()) { + initializeSystemZTTIPass(*PassRegistry::getPassRegistry()); + } + + virtual void initializePass() { + pushTTIStack(this); + } + + virtual void finalizePass() { + popTTIStack(); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + TargetTransformInfo::getAnalysisUsage(AU); + } + + // Pass identification. + static char ID; + + // Provide necessary pointer adjustments for the two base classes. + virtual void *getAdjustedAnalysisPointer(const void *ID) { + if (ID == &TargetTransformInfo::ID) + return (TargetTransformInfo*)this; + return this; + } + + /// \name Scalar TTI Implementations + /// @{ + + virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; + + virtual unsigned getIntImmCost(unsigned Opcode, unsigned Idx, + const APInt &Imm, Type *Ty) const; + virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, + const APInt &Imm, Type *Ty) const; + + /// @} +}; + +} // end anonymous namespace + +INITIALIZE_AG_PASS(SystemZTTI, TargetTransformInfo, "systemztti", + "SystemZ Target Transform Info", true, true, false) +char SystemZTTI::ID = 0; + +ImmutablePass * +llvm::createSystemZTargetTransformInfoPass(const SystemZTargetMachine *TM) { + return new SystemZTTI(TM); +} + + +//===----------------------------------------------------------------------===// +// +// SystemZ cost model. +// +//===----------------------------------------------------------------------===// + +unsigned SystemZTTI::getIntImmCost(const APInt &Imm, Type *Ty) const { + assert(Ty->isIntegerTy()); + + unsigned BitSize = Ty->getPrimitiveSizeInBits(); + // There is no cost model for constants with a bit size of 0. Return TCC_Free + // here, so that constant hoisting will ignore this constant. + if (BitSize == 0) + return TCC_Free; + // No cost model for operations on integers larger than 64 bit implemented yet. + if (BitSize > 64) + return TCC_Free; + + if (Imm == 0) + return TCC_Free; + + if (Imm.getBitWidth() <= 64) { + // Constants loaded via lgfi. + if (isInt<32>(Imm.getSExtValue())) + return TCC_Basic; + // Constants loaded via llilf. + if (isUInt<32>(Imm.getZExtValue())) + return TCC_Basic; + // Constants loaded via llihf: + if ((Imm.getZExtValue() & 0xffffffff) == 0) + return TCC_Basic; + + return 2 * TCC_Basic; + } + + return 4 * TCC_Basic; +} + +unsigned SystemZTTI::getIntImmCost(unsigned Opcode, unsigned Idx, + const APInt &Imm, Type *Ty) const { + assert(Ty->isIntegerTy()); + + unsigned BitSize = Ty->getPrimitiveSizeInBits(); + // There is no cost model for constants with a bit size of 0. Return TCC_Free + // here, so that constant hoisting will ignore this constant. + if (BitSize == 0) + return TCC_Free; + // No cost model for operations on integers larger than 64 bit implemented yet. + if (BitSize > 64) + return TCC_Free; + + switch (Opcode) { + default: + return TCC_Free; + case Instruction::GetElementPtr: + // Always hoist the base address of a GetElementPtr. This prevents the + // creation of new constants for every base constant that gets constant + // folded with the offset. + if (Idx == 0) + return 2 * TCC_Basic; + return TCC_Free; + case Instruction::Store: + if (Idx == 0 && Imm.getBitWidth() <= 64) { + // Any 8-bit immediate store can by implemented via mvi. + if (BitSize == 8) + return TCC_Free; + // 16-bit immediate values can be stored via mvhhi/mvhi/mvghi. + if (isInt<16>(Imm.getSExtValue())) + return TCC_Free; + } + break; + case Instruction::ICmp: + if (Idx == 1 && Imm.getBitWidth() <= 64) { + // Comparisons against signed 32-bit immediates implemented via cgfi. + if (isInt<32>(Imm.getSExtValue())) + return TCC_Free; + // Comparisons against unsigned 32-bit immediates implemented via clgfi. + if (isUInt<32>(Imm.getZExtValue())) + return TCC_Free; + } + break; + case Instruction::Add: + case Instruction::Sub: + if (Idx == 1 && Imm.getBitWidth() <= 64) { + // We use algfi/slgfi to add/subtract 32-bit unsigned immediates. + if (isUInt<32>(Imm.getZExtValue())) + return TCC_Free; + // Or their negation, by swapping addition vs. subtraction. + if (isUInt<32>(-Imm.getSExtValue())) + return TCC_Free; + } + break; + case Instruction::Mul: + if (Idx == 1 && Imm.getBitWidth() <= 64) { + // We use msgfi to multiply by 32-bit signed immediates. + if (isInt<32>(Imm.getSExtValue())) + return TCC_Free; + } + break; + case Instruction::Or: + case Instruction::Xor: + if (Idx == 1 && Imm.getBitWidth() <= 64) { + // Masks supported by oilf/xilf. + if (isUInt<32>(Imm.getZExtValue())) + return TCC_Free; + // Masks supported by oihf/xihf. + if ((Imm.getZExtValue() & 0xffffffff) == 0) + return TCC_Free; + } + break; + case Instruction::And: + if (Idx == 1 && Imm.getBitWidth() <= 64) { + // Any 32-bit AND operation can by implemented via nilf. + if (BitSize <= 32) + return TCC_Free; + // 64-bit masks supported by nilf. + if (isUInt<32>(~Imm.getZExtValue())) + return TCC_Free; + // 64-bit masks supported by nilh. + if ((Imm.getZExtValue() & 0xffffffff) == 0xffffffff) + return TCC_Free; + // Some 64-bit AND operations can be implemented via risbg. + unsigned Start, End; + if (TII->isRxSBGMask(Imm.getZExtValue(), BitSize, Start, End)) + return TCC_Free; + } + break; + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + // Always return TCC_Free for the shift value of a shift instruction. + if (Idx == 1) + return TCC_Free; + break; + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::BitCast: + case Instruction::PHI: + case Instruction::Call: + case Instruction::Select: + case Instruction::Ret: + case Instruction::Load: + break; + } + + return SystemZTTI::getIntImmCost(Imm, Ty); +} + +unsigned SystemZTTI::getIntImmCost(Intrinsic::ID IID, unsigned Idx, + const APInt &Imm, Type *Ty) const { + assert(Ty->isIntegerTy()); + + unsigned BitSize = Ty->getPrimitiveSizeInBits(); + // There is no cost model for constants with a bit size of 0. Return TCC_Free + // here, so that constant hoisting will ignore this constant. + if (BitSize == 0) + return TCC_Free; + // No cost model for operations on integers larger than 64 bit implemented yet. + if (BitSize > 64) + return TCC_Free; + + switch (IID) { + default: + return TCC_Free; + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::usub_with_overflow: + // These get expanded to include a normal addition/subtraction. + if (Idx == 1 && Imm.getBitWidth() <= 64) { + if (isUInt<32>(Imm.getZExtValue())) + return TCC_Free; + if (isUInt<32>(-Imm.getSExtValue())) + return TCC_Free; + } + break; + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: + // These get expanded to include a normal multiplication. + if (Idx == 1 && Imm.getBitWidth() <= 64) { + if (isInt<32>(Imm.getSExtValue())) + return TCC_Free; + } + break; + case Intrinsic::experimental_stackmap: + if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) + return TCC_Free; + break; + case Intrinsic::experimental_patchpoint_void: + case Intrinsic::experimental_patchpoint_i64: + if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) + return TCC_Free; + break; + } + return SystemZTTI::getIntImmCost(Imm, Ty); +} + Index: test/CodeGen/SystemZ/int-cmp-47.ll =================================================================== --- test/CodeGen/SystemZ/int-cmp-47.ll.orig +++ test/CodeGen/SystemZ/int-cmp-47.ll @@ -309,7 +309,8 @@ exit: define void @f17(i64 %a) { ; CHECK-LABEL: f17: ; CHECK-NOT: tmhh -; CHECK: llihh {{%r[0-5]}}, 49151 +; CHECK: srlg [[REG:%r[0-5]]], %r2, 48 +; CHECK: cgfi [[REG]], 49151 ; CHECK-NOT: tmhh ; CHECK: br %r14 entry: Index: test/CodeGen/SystemZ/int-cmp-12.ll =================================================================== --- test/CodeGen/SystemZ/int-cmp-12.ll.orig +++ test/CodeGen/SystemZ/int-cmp-12.ll @@ -49,13 +49,24 @@ define double @f4(double %a, double %b, ret double %res } -; Check the next value up, which must use a register comparison. +; Check the next value up, which can use a shifted comparison define double @f5(double %a, double %b, i64 %i1) { ; CHECK-LABEL: f5: -; CHECK: clgrjl %r2, +; CHECK: srlg [[REG:%r[0-5]]], %r2, 32 +; CHECK: cgije [[REG]], 0 ; CHECK: ldr %f0, %f2 ; CHECK: br %r14 %cond = icmp ult i64 %i1, 4294967296 %res = select i1 %cond, double %a, double %b ret double %res } +; Check the next value up, which must use a register comparison. +define double @f6(double %a, double %b, i64 %i1) { +; CHECK-LABEL: f6: +; CHECK: clgrjl %r2, +; CHECK: ldr %f0, %f2 +; CHECK: br %r14 + %cond = icmp ult i64 %i1, 4294967297 + %res = select i1 %cond, double %a, double %b + ret double %res +}
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor