forked from OSchip/llvm-project
[RISCV] Add RISCV-specific TargetTransformInfo
Summary: LLVM Allows Targets to provide information that guides optimisations made to LLVM IR. This is done with callbacks on a TargetTransformInfo object. This patch adds a TargetTransformInfo class for RISC-V. This will allow us to implement RISC-V specific callbacks as they become necessary. This commit also adds the getIntImmCost callbacks, and tests them with a simple constant hoisting test. Our immediate costs are on the conservative side, for the moment, but we prevent hoisting in most circumstances anyway. Previous review was on D63007 Reviewers: asb, luismarques Reviewed By: asb Subscribers: ributzka, MaskRay, llvm-commits, Jim, benna, psnobl, jocewei, PkmX, rkruppe, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, apazos, simoncook, johnrusso, rbar, hiraditya, mgorny Tags: #llvm Differential Revision: https://reviews.llvm.org/D63433 llvm-svn: 364046
This commit is contained in:
parent
aa9b6468bd
commit
96c8bc7956
|
@ -27,6 +27,7 @@ add_llvm_target(RISCVCodeGen
|
||||||
RISCVSubtarget.cpp
|
RISCVSubtarget.cpp
|
||||||
RISCVTargetMachine.cpp
|
RISCVTargetMachine.cpp
|
||||||
RISCVTargetObjectFile.cpp
|
RISCVTargetObjectFile.cpp
|
||||||
|
RISCVTargetTransformInfo.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(AsmParser)
|
add_subdirectory(AsmParser)
|
||||||
|
|
|
@ -29,6 +29,6 @@ has_disassembler = 1
|
||||||
type = Library
|
type = Library
|
||||||
name = RISCVCodeGen
|
name = RISCVCodeGen
|
||||||
parent = RISCV
|
parent = RISCV
|
||||||
required_libraries = AsmPrinter Core CodeGen MC RISCVDesc
|
required_libraries = Analysis AsmPrinter Core CodeGen MC RISCVDesc
|
||||||
RISCVInfo RISCVUtils SelectionDAG Support Target
|
RISCVInfo RISCVUtils SelectionDAG Support Target
|
||||||
add_to_library_groups = RISCV
|
add_to_library_groups = RISCV
|
||||||
|
|
|
@ -10,11 +10,13 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "RISCV.h"
|
|
||||||
#include "RISCVTargetMachine.h"
|
#include "RISCVTargetMachine.h"
|
||||||
|
#include "RISCV.h"
|
||||||
#include "RISCVTargetObjectFile.h"
|
#include "RISCVTargetObjectFile.h"
|
||||||
|
#include "RISCVTargetTransformInfo.h"
|
||||||
#include "TargetInfo/RISCVTargetInfo.h"
|
#include "TargetInfo/RISCVTargetInfo.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||||
#include "llvm/CodeGen/Passes.h"
|
#include "llvm/CodeGen/Passes.h"
|
||||||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||||
#include "llvm/CodeGen/TargetPassConfig.h"
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
||||||
|
@ -61,6 +63,11 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
|
||||||
initAsmInfo();
|
initAsmInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TargetTransformInfo
|
||||||
|
RISCVTargetMachine::getTargetTransformInfo(const Function &F) {
|
||||||
|
return TargetTransformInfo(RISCVTTIImpl(this, F));
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class RISCVPassConfig : public TargetPassConfig {
|
class RISCVPassConfig : public TargetPassConfig {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -39,6 +39,8 @@ public:
|
||||||
TargetLoweringObjectFile *getObjFileLowering() const override {
|
TargetLoweringObjectFile *getObjFileLowering() const override {
|
||||||
return TLOF.get();
|
return TLOF.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TargetTransformInfo getTargetTransformInfo(const Function &F) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
//===-- RISCVTargetTransformInfo.cpp - RISC-V specific TTI ----------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "RISCVTargetTransformInfo.h"
|
||||||
|
#include "Utils/RISCVMatInt.h"
|
||||||
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||||
|
#include "llvm/CodeGen/BasicTTIImpl.h"
|
||||||
|
#include "llvm/CodeGen/TargetLowering.h"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "riscvtti"
|
||||||
|
|
||||||
|
int RISCVTTIImpl::getIntImmCost(const APInt &Imm, Type *Ty) {
|
||||||
|
assert(Ty->isIntegerTy() &&
|
||||||
|
"getIntImmCost can only estimate cost of materialising integers");
|
||||||
|
|
||||||
|
// We have a Zero register, so 0 is always free.
|
||||||
|
if (Imm == 0)
|
||||||
|
return TTI::TCC_Free;
|
||||||
|
|
||||||
|
// Otherwise, we check how many instructions it will take to materialise.
|
||||||
|
const DataLayout &DL = getDataLayout();
|
||||||
|
return RISCVMatInt::getIntMatCost(Imm, DL.getTypeSizeInBits(Ty),
|
||||||
|
getST()->is64Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
int RISCVTTIImpl::getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
|
||||||
|
Type *Ty) {
|
||||||
|
assert(Ty->isIntegerTy() &&
|
||||||
|
"getIntImmCost can only estimate cost of materialising integers");
|
||||||
|
|
||||||
|
// We have a Zero register, so 0 is always free.
|
||||||
|
if (Imm == 0)
|
||||||
|
return TTI::TCC_Free;
|
||||||
|
|
||||||
|
// Some instructions in RISC-V can take a 12-bit immediate. Some of these are
|
||||||
|
// commutative, in others the immediate comes from a specific argument index.
|
||||||
|
bool Takes12BitImm = false;
|
||||||
|
unsigned ImmArgIdx = ~0U;
|
||||||
|
|
||||||
|
switch (Opcode) {
|
||||||
|
case Instruction::GetElementPtr:
|
||||||
|
// Never hoist any arguments to a GetElementPtr. CodeGenPrepare will
|
||||||
|
// split up large offsets in GEP into better parts than ConstantHoisting
|
||||||
|
// can.
|
||||||
|
return TTI::TCC_Free;
|
||||||
|
case Instruction::Add:
|
||||||
|
case Instruction::And:
|
||||||
|
case Instruction::Or:
|
||||||
|
case Instruction::Xor:
|
||||||
|
case Instruction::Mul:
|
||||||
|
Takes12BitImm = true;
|
||||||
|
break;
|
||||||
|
case Instruction::Sub:
|
||||||
|
case Instruction::Shl:
|
||||||
|
case Instruction::LShr:
|
||||||
|
case Instruction::AShr:
|
||||||
|
Takes12BitImm = true;
|
||||||
|
ImmArgIdx = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Takes12BitImm) {
|
||||||
|
// Check immediate is the correct argument...
|
||||||
|
if (Instruction::isCommutative(Opcode) || Idx == ImmArgIdx) {
|
||||||
|
// ... and fits into the 12-bit immediate.
|
||||||
|
if (getTLI()->isLegalAddImmediate(Imm.getSExtValue()))
|
||||||
|
return TTI::TCC_Free;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, use the full materialisation cost.
|
||||||
|
return getIntImmCost(Imm, Ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default, prevent hoisting.
|
||||||
|
return TTI::TCC_Free;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RISCVTTIImpl::getIntImmCost(Intrinsic::ID IID, unsigned Idx,
|
||||||
|
const APInt &Imm, Type *Ty) {
|
||||||
|
// Prevent hoisting in unknown cases.
|
||||||
|
return TTI::TCC_Free;
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
//===- RISCVTargetTransformInfo.h - RISC-V specific TTI ---------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// \file
|
||||||
|
/// This file defines a TargetTransformInfo::Concept conforming object specific
|
||||||
|
/// to the RISC-V 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_RISCV_RISCVTARGETTRANSFORMINFO_H
|
||||||
|
#define LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
|
||||||
|
|
||||||
|
#include "RISCVSubtarget.h"
|
||||||
|
#include "RISCVTargetMachine.h"
|
||||||
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||||
|
#include "llvm/CodeGen/BasicTTIImpl.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
|
||||||
|
using BaseT = BasicTTIImplBase<RISCVTTIImpl>;
|
||||||
|
using TTI = TargetTransformInfo;
|
||||||
|
|
||||||
|
friend BaseT;
|
||||||
|
|
||||||
|
const RISCVSubtarget *ST;
|
||||||
|
const RISCVTargetLowering *TLI;
|
||||||
|
|
||||||
|
const RISCVSubtarget *getST() const { return ST; }
|
||||||
|
const RISCVTargetLowering *getTLI() const { return TLI; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RISCVTTIImpl(const RISCVTargetMachine *TM, const Function &F)
|
||||||
|
: BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)),
|
||||||
|
TLI(ST->getTargetLowering()) {}
|
||||||
|
|
||||||
|
int getIntImmCost(const APInt &Imm, Type *Ty);
|
||||||
|
int getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty);
|
||||||
|
int getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
|
||||||
|
Type *Ty);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_LIB_TARGET_RISCV_RISCVTARGETTRANSFORMINFO_H
|
|
@ -11,19 +11,19 @@ define void @imm32_cse() nounwind {
|
||||||
; RV32I-LABEL: imm32_cse:
|
; RV32I-LABEL: imm32_cse:
|
||||||
; RV32I: # %bb.0:
|
; RV32I: # %bb.0:
|
||||||
; RV32I-NEXT: lui a0, 1
|
; RV32I-NEXT: lui a0, 1
|
||||||
; RV32I-NEXT: addi a1, a0, 1
|
; RV32I-NEXT: addi a0, a0, 1
|
||||||
; RV32I-NEXT: lui a2, %hi(src)
|
; RV32I-NEXT: lui a1, %hi(src)
|
||||||
; RV32I-NEXT: lw a3, %lo(src)(a2)
|
; RV32I-NEXT: lw a2, %lo(src)(a1)
|
||||||
; RV32I-NEXT: add a1, a3, a1
|
; RV32I-NEXT: add a2, a2, a0
|
||||||
; RV32I-NEXT: lui a3, %hi(dst)
|
; RV32I-NEXT: lui a3, %hi(dst)
|
||||||
; RV32I-NEXT: sw a1, %lo(dst)(a3)
|
; RV32I-NEXT: sw a2, %lo(dst)(a3)
|
||||||
; RV32I-NEXT: addi a1, a0, 2
|
; RV32I-NEXT: lw a2, %lo(src)(a1)
|
||||||
; RV32I-NEXT: lw a4, %lo(src)(a2)
|
; RV32I-NEXT: add a2, a2, a0
|
||||||
; RV32I-NEXT: add a1, a4, a1
|
; RV32I-NEXT: addi a2, a2, 1
|
||||||
; RV32I-NEXT: sw a1, %lo(dst)(a3)
|
; RV32I-NEXT: sw a2, %lo(dst)(a3)
|
||||||
; RV32I-NEXT: addi a0, a0, 3
|
; RV32I-NEXT: lw a1, %lo(src)(a1)
|
||||||
; RV32I-NEXT: lw a1, %lo(src)(a2)
|
|
||||||
; RV32I-NEXT: add a0, a1, a0
|
; RV32I-NEXT: add a0, a1, a0
|
||||||
|
; RV32I-NEXT: addi a0, a0, 2
|
||||||
; RV32I-NEXT: sw a0, %lo(dst)(a3)
|
; RV32I-NEXT: sw a0, %lo(dst)(a3)
|
||||||
; RV32I-NEXT: ret
|
; RV32I-NEXT: ret
|
||||||
%1 = load volatile i32, i32* @src
|
%1 = load volatile i32, i32* @src
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
; RUN: opt -mtriple=riscv32-unknown-elf -S -consthoist < %s | FileCheck %s
|
||||||
|
; RUN: opt -mtriple=riscv64-unknown-elf -S -consthoist < %s | FileCheck %s
|
||||||
|
|
||||||
|
; Check that we don't hoist immediates with small values.
|
||||||
|
define i64 @test1(i64 %a) nounwind {
|
||||||
|
; CHECK-LABEL: test1
|
||||||
|
; CHECK-NOT: %const = bitcast i64 2 to i64
|
||||||
|
%1 = mul i64 %a, 2
|
||||||
|
%2 = add i64 %1, 2
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
; Check that we don't hoist immediates with small values.
|
||||||
|
define i64 @test2(i64 %a) nounwind {
|
||||||
|
; CHECK-LABEL: test2
|
||||||
|
; CHECK-NOT: %const = bitcast i64 2047 to i64
|
||||||
|
%1 = mul i64 %a, 2047
|
||||||
|
%2 = add i64 %1, 2047
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
; Check that we hoist immediates with large values.
|
||||||
|
define i64 @test3(i64 %a) nounwind {
|
||||||
|
; CHECK-LABEL: test3
|
||||||
|
; CHECK: %const = bitcast i64 32767 to i64
|
||||||
|
%1 = mul i64 %a, 32767
|
||||||
|
%2 = add i64 %1, 32767
|
||||||
|
ret i64 %2
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
if not 'RISCV' in config.root.targets:
|
||||||
|
config.unsupported = True
|
Loading…
Reference in New Issue