Index: include/llvm/Analysis/TargetTransformInfo.h =================================================================== --- include/llvm/Analysis/TargetTransformInfo.h +++ include/llvm/Analysis/TargetTransformInfo.h @@ -262,7 +262,7 @@ /// pointer with this address space is expected to be legal but slower /// compared to the same memory location accessed through a pointer with a /// different address space. - // + /// /// This is for for targets with different pointer representations which can /// be converted with the addrspacecast instruction. If a pointer is converted /// to this address space, optimizations should attempt to replace the access @@ -272,6 +272,14 @@ /// optimize away. unsigned getFlatAddressSpace() const; + /// Returns the address space ID that switch lookup tables should be placed + /// into. + /// + /// This is useful for Harvard architectures where you often want to place + /// lookup tables into a different address space (for example, in AVR, lookup + /// tables reside in the 'program memory' space. + unsigned getSwitchTableAddressSpace() const; + /// \brief Test whether calls to a function lower to actual program function /// calls. /// @@ -866,6 +874,8 @@ virtual bool isSourceOfDivergence(const Value *V) = 0; virtual bool isAlwaysUniform(const Value *V) = 0; virtual unsigned getFlatAddressSpace() = 0; + virtual unsigned getSwitchTableAddressSpace() const = 0; + virtual bool isLoweredToCall(const Function *F) = 0; virtual void getUnrollingPreferences(Loop *L, ScalarEvolution &, UnrollingPreferences &UP) = 0; @@ -1059,6 +1069,10 @@ return Impl.getFlatAddressSpace(); } + unsigned getSwitchTableAddressSpace() const override { + return Impl.getSwitchTableAddressSpace(); + } + bool isLoweredToCall(const Function *F) override { return Impl.isLoweredToCall(F); } Index: include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- include/llvm/Analysis/TargetTransformInfoImpl.h +++ include/llvm/Analysis/TargetTransformInfoImpl.h @@ -588,9 +588,24 @@ } }; +/// A memory architecture where the program and the data live in +/// separate address spaces. +template +class HarvardArchitecture { +public: + static unsigned getSwitchTableAddressSpace() { return ProgramSpace; } +}; + +/// A memory architecture where the program and the data live in the +/// same address space. +class VonNeumannArchitecture { +public: + static unsigned getSwitchTableAddressSpace() { return 0; } +}; + /// \brief CRTP base class for use as a mix-in that aids implementing /// a TargetTransformInfo-compatible class. -template +template class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { private: typedef TargetTransformInfoImplBase BaseT; @@ -734,6 +749,10 @@ Operator::getOpcode(U), U->getType(), U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr); } + + unsigned getSwitchTableAddressSpace() const { + return MemArch::getSwitchTableAddressSpace(); + } }; } Index: include/llvm/CodeGen/BasicTTIImpl.h =================================================================== --- include/llvm/CodeGen/BasicTTIImpl.h +++ include/llvm/CodeGen/BasicTTIImpl.h @@ -27,6 +27,9 @@ extern cl::opt PartialUnrollingThreshold; +/// The default memory architecture. +typedef VonNeumannArchitecture DefaultMemArch; + /// \brief Base class which can be used to help build a TTI implementation. /// /// This class provides as much implementation of the TTI interface as is @@ -36,10 +39,10 @@ /// return the subtarget, and a getTLI() method to return the target lowering. /// We need these methods implemented in the derived class so that this class /// doesn't have to duplicate storage for them. -template -class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { +template +class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { private: - typedef TargetTransformInfoImplCRTPBase BaseT; + typedef TargetTransformInfoImplCRTPBase BaseT; typedef TargetTransformInfo TTI; /// Estimate a cost of shuffle as a sequence of extract and insert @@ -1164,9 +1167,10 @@ /// \brief Concrete BasicTTIImpl that can be used if no further customization /// is needed. -class BasicTTIImpl : public BasicTTIImplBase { - typedef BasicTTIImplBase BaseT; - friend class BasicTTIImplBase; +template +class BasicTTIImpl : public BasicTTIImplBase, MemArch> { + typedef BasicTTIImplBase BaseT; + friend class BasicTTIImplBase; const TargetSubtargetInfo *ST; const TargetLoweringBase *TLI; @@ -1175,7 +1179,9 @@ const TargetLoweringBase *getTLI() const { return TLI; } public: - explicit BasicTTIImpl(const TargetMachine *ST, const Function &F); + explicit BasicTTIImpl(const TargetMachine *TM, const Function &F) + : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), + TLI(ST->getTargetLowering()) {} }; } Index: lib/Analysis/TargetTransformInfo.cpp =================================================================== --- lib/Analysis/TargetTransformInfo.cpp +++ lib/Analysis/TargetTransformInfo.cpp @@ -34,9 +34,9 @@ /// classes. /// /// This is used when no target specific information is available. -struct NoTTIImpl : TargetTransformInfoImplCRTPBase { +struct NoTTIImpl : TargetTransformInfoImplCRTPBase { explicit NoTTIImpl(const DataLayout &DL) - : TargetTransformInfoImplCRTPBase(DL) {} + : TargetTransformInfoImplCRTPBase(DL) {} }; } @@ -118,6 +118,10 @@ return TTIImpl->getFlatAddressSpace(); } +unsigned TargetTransformInfo::getSwitchTableAddressSpace() const { + return TTIImpl->getSwitchTableAddressSpace(); +} + bool TargetTransformInfo::isLoweredToCall(const Function *F) const { return TTIImpl->isLoweredToCall(F); } Index: lib/CodeGen/BasicTargetTransformInfo.cpp =================================================================== --- lib/CodeGen/BasicTargetTransformInfo.cpp +++ lib/CodeGen/BasicTargetTransformInfo.cpp @@ -31,6 +31,3 @@ cl::desc("Threshold for partial unrolling"), cl::Hidden); -BasicTTIImpl::BasicTTIImpl(const TargetMachine *TM, const Function &F) - : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), - TLI(ST->getTargetLowering()) {} Index: lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- lib/CodeGen/LLVMTargetMachine.cpp +++ lib/CodeGen/LLVMTargetMachine.cpp @@ -85,7 +85,7 @@ TargetIRAnalysis LLVMTargetMachine::getTargetIRAnalysis() { return TargetIRAnalysis([this](const Function &F) { - return TargetTransformInfo(BasicTTIImpl(this, F)); + return TargetTransformInfo(BasicTTIImpl<>(this, F)); }); } Index: lib/Target/AVR/AVRTargetMachine.h =================================================================== --- lib/Target/AVR/AVRTargetMachine.h +++ lib/Target/AVR/AVRTargetMachine.h @@ -35,6 +35,8 @@ const AVRSubtarget *getSubtargetImpl() const; const AVRSubtarget *getSubtargetImpl(const Function &) const override; + TargetIRAnalysis getTargetIRAnalysis() override; + TargetLoweringObjectFile *getObjFileLowering() const override { return this->TLOF.get(); } Index: lib/Target/AVR/AVRTargetMachine.cpp =================================================================== --- lib/Target/AVR/AVRTargetMachine.cpp +++ lib/Target/AVR/AVRTargetMachine.cpp @@ -21,6 +21,7 @@ #include "AVR.h" #include "AVRTargetObjectFile.h" +#include "AVRTargetTransformInfo.h" #include "MCTargetDesc/AVRMCTargetDesc.h" namespace llvm { @@ -53,6 +54,12 @@ initAsmInfo(); } +TargetIRAnalysis AVRTargetMachine::getTargetIRAnalysis() { + return TargetIRAnalysis([this](const Function &F) { + return TargetTransformInfo(AVRTTIImpl(this, F)); + }); +} + namespace { /// AVR Code Generator Pass Configuration Options. class AVRPassConfig : public TargetPassConfig { Index: lib/Target/AVR/AVRTargetTransformInfo.h =================================================================== --- /dev/null +++ lib/Target/AVR/AVRTargetTransformInfo.h @@ -0,0 +1,49 @@ +//===---- AVRTargetTransformInfo.h - AVR specific TTI -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file a TargetTransformInfo::Concept conforming object specific to the +// AVR 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H +#define LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H + +#include "AVR.h" +#include "AVRSubtarget.h" +#include "AVRTargetMachine.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/BasicTTIImpl.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { +class AVRTTIImpl : public BasicTTIImplBase> { + typedef BasicTTIImplBase> BaseT; + typedef TargetTransformInfo TTI; + friend BaseT; + + const AVRSubtarget *ST; + const AVRTargetLowering *TLI; + + const AVRSubtarget *getST() const { return ST; } + const AVRTargetLowering *getTLI() const { return TLI; } + +public: + explicit AVRTTIImpl(const AVRTargetMachine *TM, const Function &F) + : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), + TLI(ST->getTargetLowering()) {} + + unsigned getSwitchTableAddressSpace() const { return AVR::ProgramMemory; } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AVR_AVRTARGETTRANSFORMINFO_H Index: lib/Target/AVR/LLVMBuild.txt =================================================================== --- lib/Target/AVR/LLVMBuild.txt +++ lib/Target/AVR/LLVMBuild.txt @@ -30,6 +30,17 @@ type = Library name = AVRCodeGen parent = AVR -required_libraries = AsmPrinter CodeGen Core MC AVRAsmPrinter AVRDesc AVRInfo SelectionDAG Support Target +required_libraries = + Analysis + AsmPrinter + CodeGen + Core + MC + AVRAsmPrinter + AVRDesc + AVRInfo + SelectionDAG + Support + Target add_to_library_groups = AVR Index: lib/Target/Mips/MipsTargetMachine.cpp =================================================================== --- lib/Target/Mips/MipsTargetMachine.cpp +++ lib/Target/Mips/MipsTargetMachine.cpp @@ -260,7 +260,7 @@ } DEBUG(errs() << "Target Transform Info Pass Added\n"); - return TargetTransformInfo(BasicTTIImpl(this, F)); + return TargetTransformInfo(BasicTTIImpl<>(this, F)); }); } Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -4781,7 +4781,8 @@ SwitchLookupTable( Module &M, uint64_t TableSize, ConstantInt *Offset, const SmallVectorImpl> &Values, - Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName); + Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName, + const TargetTransformInfo &TTI); /// Build instructions with Builder to retrieve the value at /// the position given by Index in the lookup table. @@ -4835,7 +4836,8 @@ SwitchLookupTable::SwitchLookupTable( Module &M, uint64_t TableSize, ConstantInt *Offset, const SmallVectorImpl> &Values, - Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName) + Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName, + const TargetTransformInfo &TTI) : SingleValue(nullptr), BitMap(nullptr), BitMapElementTy(nullptr), LinearOffset(nullptr), LinearMultiplier(nullptr), Array(nullptr) { assert(Values.size() && "Can't build lookup table without values!"); @@ -4943,7 +4945,10 @@ Array = new GlobalVariable(M, ArrayTy, /*constant=*/true, GlobalVariable::PrivateLinkage, Initializer, - "switch.table." + FuncName); + "switch.table." + FuncName, + /*InsertBefore=*/nullptr, + GlobalValue::NotThreadLocal, + TTI.getSwitchTableAddressSpace()); Array->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); Kind = ArrayKind; } @@ -5335,7 +5340,7 @@ Constant *DV = NeedMask ? ResultLists[PHI][0].second : DefaultResults[PHI]; StringRef FuncName = SI->getParent()->getParent()->getName(); SwitchLookupTable Table(Mod, TableSize, MinCaseVal, ResultList, DV, DL, - FuncName); + FuncName, TTI); Value *Result = Table.BuildLookup(TableIndex, Builder); Index: test/CodeGen/AVR/switch-lookup-table-in-progmem-space.ll =================================================================== --- /dev/null +++ test/CodeGen/AVR/switch-lookup-table-in-progmem-space.ll @@ -0,0 +1,61 @@ +; RUN: opt -S -mtriple=avr -latesimplifycfg < %s | FileCheck %s + +; Switch lookup tables should be placed in program memory (address space 1). + +%MyType = type { i8, [0 x i8], [0 x i8] } + +define i8 @foo(i8) { +start: + %_0 = alloca %MyType + +; CHECK: @switch.table.foo = {{.*}}addrspace(1) constant [15 x i8] c"\01\01\01\01\01\00\00\00\00\00\00\00\00\00\01" + switch i8 %0, label %bb7 [ + i8 0, label %bb1 + i8 1, label %bb2 + i8 2, label %bb3 + i8 3, label %bb4 + i8 4, label %bb5 + i8 14, label %bb6 + ] + +bb1: + %1 = getelementptr inbounds %MyType, %MyType* %_0, i32 0, i32 0 + store i8 1, i8* %1 + br label %bb8 + +bb2: + %2 = getelementptr inbounds %MyType, %MyType* %_0, i32 0, i32 0 + store i8 1, i8* %2 + br label %bb8 + +bb3: + %3 = getelementptr inbounds %MyType, %MyType* %_0, i32 0, i32 0 + store i8 1, i8* %3 + br label %bb8 + +bb4: + %4 = getelementptr inbounds %MyType, %MyType* %_0, i32 0, i32 0 + store i8 1, i8* %4 + br label %bb8 + +bb5: + %5 = getelementptr inbounds %MyType, %MyType* %_0, i32 0, i32 0 + store i8 1, i8* %5 + br label %bb8 + +bb6: + %6 = getelementptr inbounds %MyType, %MyType* %_0, i32 0, i32 0 + store i8 1, i8* %6 + br label %bb8 + +bb7: + %7 = getelementptr inbounds %MyType, %MyType* %_0, i32 0, i32 0 + store i8 0, i8* %7 + br label %bb8 + +bb8: + %8 = bitcast %MyType* %_0 to i8* + %9 = load i8, i8* %8, align 1 + ret i8 %9 +} +