[AMDGPU] Lower null pointers in static variable initializer

For amdgcn target Clang generates addrspacecast to represent null pointers in private and local address spaces.

    In LLVM codegen, the static variable initializer is lowered by virtual function AsmPrinter::lowerConstant which is target generic. Since addrspacecast is target specific, AsmPrinter::lowerConst

    This patch overrides AsmPrinter::lowerConstant with AMDGPUAsmPrinter::lowerConstant, which is able to lower the target-specific addrspacecast in the null pointer representation so that -1 is co

    Differential Revision: https://reviews.llvm.org/D29284

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294265 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Yaxun Liu 2017-02-07 00:43:21 +00:00
parent 85df5176ce
commit d14a49a05f
4 changed files with 152 additions and 0 deletions

View File

@ -111,6 +111,11 @@ public:
/// pseudo lowering.
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
/// \brief Lower the specified LLVM Constant to an MCExpr.
/// The AsmPrinter::lowerConstantof does not know how to lower
/// addrspacecast, therefore they should be lowered by this function.
const MCExpr *lowerConstant(const Constant *CV) override;
/// \brief tblgen'erated driver function for lowering simple MI->MC pseudo
/// instructions.
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,

View File

@ -151,6 +151,28 @@ bool AMDGPUAsmPrinter::lowerOperand(const MachineOperand &MO,
return MCInstLowering.lowerOperand(MO, MCOp);
}
const MCExpr *AMDGPUAsmPrinter::lowerConstant(const Constant *CV) {
// TargetMachine does not support llvm-style cast. Use C++-style cast.
// This is safe since TM is always of type AMDGPUTargetMachine or its
// derived class.
auto *AT = static_cast<AMDGPUTargetMachine*>(&TM);
auto *CE = dyn_cast<ConstantExpr>(CV);
// Lower null pointers in private and local address space.
// Clang generates addrspacecast for null pointers in private and local
// address space, which needs to be lowered.
if (CE && CE->getOpcode() == Instruction::AddrSpaceCast) {
auto Op = CE->getOperand(0);
auto SrcAddr = Op->getType()->getPointerAddressSpace();
if (Op->isNullValue() && AT->getNullPointerValue(SrcAddr) == 0) {
auto DstAddr = CE->getType()->getPointerAddressSpace();
return MCConstantExpr::create(AT->getNullPointerValue(DstAddr),
OutContext);
}
}
return AsmPrinter::lowerConstant(CV);
}
void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (emitPseudoExpansionLowering(*OutStreamer, MI))
return;

View File

@ -59,6 +59,18 @@ public:
}
void adjustPassManager(PassManagerBuilder &) override;
/// Get the integer value of a null pointer in the given address space.
uint64_t getNullPointerValue(unsigned AddrSpace) const {
switch(AddrSpace) {
case AMDGPUAS::PRIVATE_ADDRESS:
case AMDGPUAS::LOCAL_ADDRESS:
case AMDGPUAS::REGION_ADDRESS:
return -1;
default:
return 0;
}
}
};
//===----------------------------------------------------------------------===//

View File

@ -0,0 +1,113 @@
;RUN: llc < %s -march=amdgcn -verify-machineinstrs | FileCheck %s
%struct.S = type { i32*, i32 addrspace(1)*, i32 addrspace(2)*, i32 addrspace(3)*, i32 addrspace(4)*, i32 addrspace(5)*}
; CHECK-LABEL: nullptr_priv:
; CHECK-NEXT: .long -1
@nullptr_priv = global i32* addrspacecast (i32 addrspace(4)* null to i32*)
; CHECK-LABEL: nullptr_glob:
; CHECK-NEXT: .quad 0
@nullptr_glob = global i32 addrspace(1)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(1)*)
; CHECK-LABEL: nullptr_const:
; CHECK-NEXT: .quad 0
@nullptr_const = global i32 addrspace(2)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(2)*)
; CHECK-LABEL: nullptr_local:
; CHECK-NEXT: .long -1
@nullptr_local = global i32 addrspace(3)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(3)*)
; CHECK-LABEL: nullptr_region:
; CHECK-NEXT: .long -1
@nullptr_region = global i32 addrspace(5)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(5)*)
; CHECK-LABEL: nullptr6:
; CHECK-NEXT: .long 0
@nullptr6 = global i32 addrspace(6)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(6)*)
; CHECK-LABEL: nullptr7:
; CHECK-NEXT: .long 0
@nullptr7 = global i32 addrspace(7)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(7)*)
; CHECK-LABEL: nullptr8:
; CHECK-NEXT: .long 0
@nullptr8 = global i32 addrspace(8)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(8)*)
; CHECK-LABEL: nullptr9:
; CHECK-NEXT: .long 0
@nullptr9 = global i32 addrspace(9)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(9)*)
; CHECK-LABEL: nullptr10:
; CHECK-NEXT: .long 0
@nullptr10 = global i32 addrspace(10)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(10)*)
; CHECK-LABEL: nullptr11:
; CHECK-NEXT: .long 0
@nullptr11 = global i32 addrspace(11)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(11)*)
; CHECK-LABEL: nullptr12:
; CHECK-NEXT: .long 0
@nullptr12 = global i32 addrspace(12)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(12)*)
; CHECK-LABEL: nullptr13:
; CHECK-NEXT: .long 0
@nullptr13 = global i32 addrspace(13)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(13)*)
; CHECK-LABEL: nullptr14:
; CHECK-NEXT: .long 0
@nullptr14 = global i32 addrspace(14)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(14)*)
; CHECK-LABEL: nullptr15:
; CHECK-NEXT: .long 0
@nullptr15 = global i32 addrspace(15)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(15)*)
; CHECK-LABEL: nullptr16:
; CHECK-NEXT: .long 0
@nullptr16 = global i32 addrspace(16)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(16)*)
; CHECK-LABEL: nullptr17:
; CHECK-NEXT: .long 0
@nullptr17 = global i32 addrspace(17)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(17)*)
; CHECK-LABEL: nullptr18:
; CHECK-NEXT: .long 0
@nullptr18 = global i32 addrspace(18)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(18)*)
; CHECK-LABEL: nullptr19:
; CHECK-NEXT: .long 0
@nullptr19 = global i32 addrspace(19)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(19)*)
; CHECK-LABEL: nullptr20:
; CHECK-NEXT: .long 0
@nullptr20 = global i32 addrspace(20)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(20)*)
; CHECK-LABEL: nullptr21:
; CHECK-NEXT: .long 0
@nullptr21 = global i32 addrspace(21)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(21)*)
; CHECK-LABEL: nullptr22:
; CHECK-NEXT: .long 0
@nullptr22 = global i32 addrspace(22)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(22)*)
; CHECK-LABEL: nullptr23:
; CHECK-NEXT: .long 0
@nullptr23 = global i32 addrspace(23)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(23)*)
; CHECK-LABEL: structWithPointers:
; CHECK-NEXT: .long -1
; CHECK-NEXT: .zero 4
; CHECK-NEXT: .quad 0
; CHECK-NEXT: .quad 0
; CHECK-NEXT: .long -1
; CHECK-NEXT: .zero 4
; CHECK-NEXT: .quad 0
; CHECK-NEXT: .long -1
; CHECK-NEXT: .zero 4
@structWithPointers = addrspace(1) global %struct.S {
i32* addrspacecast (i32 addrspace(4)* null to i32*),
i32 addrspace(1)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(1)*),
i32 addrspace(2)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(2)*),
i32 addrspace(3)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(3)*),
i32 addrspace(4)* null,
i32 addrspace(5)* addrspacecast (i32 addrspace(4)* null to i32 addrspace(5)*)}, align 4