[IR] Introduce the ptrtoaddr instruction

This introduces a new `ptrtoaddr` instruction which is similar to
`ptrtoint` but has two differences:

1) Unlike `ptrtoint`, `ptrtoaddr` does not capture provenance
2) `ptrtoaddr` only extracts (and then extends/truncates) the low
   index-width bits of the pointer

For most architectures, difference 2) does not matter since index (address)
width and pointer representation width are the same, but this does make a
difference for architectures that have pointers that aren't just plain
integer addresses such as AMDGPU fat pointers or CHERI capabilities.

This commit introduces textual and bitcode IR support as well as basic code
generation, but optimization passes do not handle the new instruction yet
so it may result in worse code than using ptrtoint. Follow-up changes will
update capture tracking, etc. for the new instruction.

RFC: https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/54

Reviewed By: nikic

Pull Request: https://github.com/llvm/llvm-project/pull/139357
This commit is contained in:
Alexander Richardson 2025-08-08 10:12:39 -07:00 committed by GitHub
parent 90e8c8e718
commit 3a4b351ba1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
52 changed files with 830 additions and 162 deletions

View File

@ -5175,6 +5175,8 @@ The following is the syntax for constant expressions:
Perform the :ref:`trunc operation <i_trunc>` on constants.
``ptrtoint (CST to TYPE)``
Perform the :ref:`ptrtoint operation <i_ptrtoint>` on constants.
``ptrtoaddr (CST to TYPE)``
Perform the :ref:`ptrtoaddr operation <i_ptrtoaddr>` on constants.
``inttoptr (CST to TYPE)``
Perform the :ref:`inttoptr operation <i_inttoptr>` on constants.
This one is *really* dangerous!
@ -12523,6 +12525,58 @@ Example:
%Y = ptrtoint ptr %P to i64 ; yields zero extension on 32-bit architecture
%Z = ptrtoint <4 x ptr> %P to <4 x i64>; yields vector zero extension for a vector of addresses on 32-bit architecture
.. _i_ptrtoaddr:
'``ptrtoaddr .. to``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
<result> = ptrtoaddr <ty> <value> to <ty2> ; yields ty2
Overview:
"""""""""
The '``ptrtoaddr``' instruction converts the pointer or a vector of
pointers ``value`` to the underlying integer address (or vector of addresses) of
type ``ty2``. This is different from :ref:`ptrtoint <i_ptrtoint>` in that it
only operates on the index bits of the pointer and ignores all other bits, and
does not capture the provenance of the pointer.
Arguments:
""""""""""
The '``ptrtoaddr``' instruction takes a ``value`` to cast, which must be
a value of type :ref:`pointer <t_pointer>` or a vector of pointers, and a
type to cast it to ``ty2``, which must be must be the :ref:`integer <t_integer>`
type (or vector of integers) matching the pointer index width of the address
space of ``ty``.
Semantics:
""""""""""
The '``ptrtoaddr``' instruction converts ``value`` to integer type ``ty2`` by
interpreting the lowest index-width pointer representation bits as an integer.
If the address size and the pointer representation size are the same and
``value`` and ``ty2`` are the same size, then nothing is done (*no-op cast*)
other than a type change.
The ``ptrtoaddr`` instruction always :ref:`captures the address but not the provenance <pointercapture>`
of the pointer argument.
Example:
""""""""
This example assumes pointers in address space 1 are 64 bits in size with an
address width of 32 bits (``p1:64:64:64:32`` :ref:`datalayout string<langref_datalayout>`)
.. code-block:: llvm
%X = ptrtoaddr ptr addrspace(1) %P to i32 ; extracts low 32 bits of pointer
%Y = ptrtoaddr <4 x ptr addrspace(1)> %P to <4 x i32>; yields vector of low 32 bits for each pointer
.. _i_inttoptr:
'``inttoptr .. to``' Instruction

View File

@ -56,6 +56,10 @@ Makes programs 10x faster by doing Special New Thing.
Changes to the LLVM IR
----------------------
* The `ptrtoaddr` instruction was introduced. This instruction returns the
address component of a pointer type variable but unlike `ptrtoint` does not
capture provenance ([#125687](https://github.com/llvm/llvm-project/pull/125687)).
Changes to LLVM infrastructure
------------------------------

View File

@ -111,6 +111,7 @@ typedef enum {
LLVMFPTrunc = 37,
LLVMFPExt = 38,
LLVMPtrToInt = 39,
LLVMPtrToAddr = 69,
LLVMIntToPtr = 40,
LLVMBitCast = 41,
LLVMAddrSpaceCast = 60,

View File

@ -731,6 +731,13 @@ public:
return 0;
break;
}
case Instruction::PtrToAddr: {
unsigned DstSize = Dst->getScalarSizeInBits();
assert(DstSize == DL.getAddressSizeInBits(Src));
if (DL.isLegalInteger(DstSize))
return 0;
break;
}
case Instruction::PtrToInt: {
unsigned DstSize = Dst->getScalarSizeInBits();
if (DL.isLegalInteger(DstSize) &&
@ -1436,6 +1443,7 @@ public:
Op2Info, Operands, I);
}
case Instruction::IntToPtr:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::SIToFP:
case Instruction::UIToFP:

View File

@ -319,6 +319,7 @@ enum Kind {
kw_fptoui,
kw_fptosi,
kw_inttoptr,
kw_ptrtoaddr,
kw_ptrtoint,
kw_bitcast,
kw_addrspacecast,

View File

@ -456,7 +456,8 @@ enum CastOpcodes {
CAST_PTRTOINT = 9,
CAST_INTTOPTR = 10,
CAST_BITCAST = 11,
CAST_ADDRSPACECAST = 12
CAST_ADDRSPACECAST = 12,
CAST_PTRTOADDR = 13,
};
/// UnaryOpcodes - These are values used in the bitcode files to encode which

View File

@ -486,6 +486,10 @@ private:
bool translatePtrToInt(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder);
}
bool translatePtrToAddr(const User &U, MachineIRBuilder &MIRBuilder) {
// FIXME: this is not correct for pointers with addr width != pointer width
return translatePtrToInt(U, MIRBuilder);
}
bool translateTrunc(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_TRUNC, U, MIRBuilder);
}

View File

@ -1158,6 +1158,8 @@ public:
LLVM_ABI static Constant *getXor(Constant *C1, Constant *C2);
LLVM_ABI static Constant *getTrunc(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
LLVM_ABI static Constant *getPtrToAddr(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
LLVM_ABI static Constant *getPtrToInt(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
LLVM_ABI static Constant *getIntToPtr(Constant *C, Type *Ty,

View File

@ -2187,7 +2187,10 @@ public:
return CreateCast(Instruction::FPExt, V, DestTy, Name, FPMathTag,
FMFSource);
}
Value *CreatePtrToAddr(Value *V, const Twine &Name = "") {
return CreateCast(Instruction::PtrToInt, V,
BB->getDataLayout().getAddressType(V->getType()), Name);
}
Value *CreatePtrToInt(Value *V, Type *DestTy,
const Twine &Name = "") {
return CreateCast(Instruction::PtrToInt, V, DestTy, Name);

View File

@ -183,6 +183,7 @@ public:
RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst);}
RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst);}
RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);}
RetTy visitPtrToAddrInst(PtrToAddrInst &I) { DELEGATE(CastInst);}
RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);}
RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);}
RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);}

View File

@ -190,35 +190,36 @@ HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(50)
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer (bitcast)
HANDLE_CAST_INST(48, PtrToAddr, PtrToAddrInst) // Pointer -> Address
HANDLE_CAST_INST(49, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(50, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(51, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(51)
FIRST_FUNCLETPAD_INST(51)
HANDLE_FUNCLETPAD_INST(51, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(52, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(52)
FIRST_FUNCLETPAD_INST(52)
HANDLE_FUNCLETPAD_INST(52, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(53, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(53)
// Other operators...
FIRST_OTHER_INST(53)
HANDLE_OTHER_INST(53, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(54, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(55, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(57, Select , SelectInst ) // select instruction
HANDLE_USER_INST (58, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (59, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(60, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(61, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(62, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(63, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(64, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(65, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(66, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(67, Freeze, FreezeInst) // Freeze instruction.
LAST_OTHER_INST(67)
FIRST_OTHER_INST(54)
HANDLE_OTHER_INST(54, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(55, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(56, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(57, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(58, Select , SelectInst ) // select instruction
HANDLE_USER_INST (59, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (60, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(61, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(62, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(63, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(64, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(65, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(66, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(67, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(68, Freeze, FreezeInst) // Freeze instruction.
LAST_OTHER_INST(68)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST

View File

@ -4949,6 +4949,46 @@ public:
}
};
/// This class represents a cast from a pointer to an address (non-capturing
/// ptrtoint).
class PtrToAddrInst : public CastInst {
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
/// Clone an identical PtrToAddrInst.
PtrToAddrInst *cloneImpl() const;
public:
/// Constructor with insert-before-instruction semantics
PtrToAddrInst(Value *S, ///< The value to be converted
Type *Ty, ///< The type to convert to
const Twine &NameStr = "", ///< A name for the new instruction
InsertPosition InsertBefore =
nullptr ///< Where to insert the new instruction
);
/// Gets the pointer operand.
Value *getPointerOperand() { return getOperand(0); }
/// Gets the pointer operand.
const Value *getPointerOperand() const { return getOperand(0); }
/// Gets the operand index of the pointer operand.
static unsigned getPointerOperandIndex() { return 0U; }
/// Returns the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return getPointerOperand()->getType()->getPointerAddressSpace();
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Instruction *I) {
return I->getOpcode() == PtrToAddr;
}
static bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
//===----------------------------------------------------------------------===//
// BitCastInst Class
//===----------------------------------------------------------------------===//

View File

@ -595,6 +595,37 @@ struct OperandTraits<PtrToIntOperator>
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PtrToIntOperator, Value)
class PtrToAddrOperator
: public ConcreteOperator<Operator, Instruction::PtrToAddr> {
friend class PtrToAddr;
friend class ConstantExpr;
public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
Value *getPointerOperand() { return getOperand(0); }
const Value *getPointerOperand() const { return getOperand(0); }
static unsigned getPointerOperandIndex() {
return 0U; // get index for modifying correct operand
}
/// Method to return the pointer operand as a PointerType.
Type *getPointerOperandType() const { return getPointerOperand()->getType(); }
/// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return cast<PointerType>(getPointerOperandType())->getAddressSpace();
}
};
template <>
struct OperandTraits<PtrToAddrOperator>
: public FixedNumOperandTraits<PtrToAddrOperator, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PtrToAddrOperator, Value)
class BitCastOperator
: public ConcreteOperator<Operator, Instruction::BitCast> {
friend class BitCastInst;

View File

@ -2278,6 +2278,8 @@ class CastInst : public UnaryInstruction {
return Opcode::FPToSI;
case llvm::Instruction::FPExt:
return Opcode::FPExt;
case llvm::Instruction::PtrToAddr:
return Opcode::PtrToAddr;
case llvm::Instruction::PtrToInt:
return Opcode::PtrToInt;
case llvm::Instruction::IntToPtr:
@ -2364,6 +2366,8 @@ class FPToUIInst final : public CastInstImpl<Instruction::Opcode::FPToUI> {};
class FPToSIInst final : public CastInstImpl<Instruction::Opcode::FPToSI> {};
class IntToPtrInst final : public CastInstImpl<Instruction::Opcode::IntToPtr> {
};
class PtrToAddrInst final
: public CastInstImpl<Instruction::Opcode::PtrToAddr> {};
class PtrToIntInst final : public CastInstImpl<Instruction::Opcode::PtrToInt> {
};
class BitCastInst final : public CastInstImpl<Instruction::Opcode::BitCast> {};

View File

@ -118,6 +118,7 @@ DEF_INSTR(Cast, OPCODES(\
OP(FPToUI) \
OP(FPToSI) \
OP(FPExt) \
OP(PtrToAddr) \
OP(PtrToInt) \
OP(IntToPtr) \
OP(SIToFP) \

View File

@ -1485,6 +1485,9 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
switch (Opcode) {
default:
llvm_unreachable("Missing case");
case Instruction::PtrToAddr:
// TODO: Add some of the ptrtoint folds here as well.
break;
case Instruction::PtrToInt:
if (auto *CE = dyn_cast<ConstantExpr>(C)) {
Constant *FoldedValue = nullptr;

View File

@ -928,6 +928,7 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(fptoui, FPToUI);
INSTKEYWORD(fptosi, FPToSI);
INSTKEYWORD(inttoptr, IntToPtr);
INSTKEYWORD(ptrtoaddr, PtrToAddr);
INSTKEYWORD(ptrtoint, PtrToInt);
INSTKEYWORD(bitcast, BitCast);
INSTKEYWORD(addrspacecast, AddrSpaceCast);

View File

@ -4273,6 +4273,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
case lltok::kw_bitcast:
case lltok::kw_addrspacecast:
case lltok::kw_inttoptr:
case lltok::kw_ptrtoaddr:
case lltok::kw_ptrtoint: {
unsigned Opc = Lex.getUIntVal();
Type *DestTy = nullptr;
@ -7310,6 +7311,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_fptoui:
case lltok::kw_fptosi:
case lltok::kw_inttoptr:
case lltok::kw_ptrtoaddr:
case lltok::kw_ptrtoint:
return parseCast(Inst, PFS, KeywordVal);
case lltok::kw_fptrunc:

View File

@ -1283,6 +1283,7 @@ static int getDecodedCastOpcode(unsigned Val) {
case bitc::CAST_SITOFP : return Instruction::SIToFP;
case bitc::CAST_FPTRUNC : return Instruction::FPTrunc;
case bitc::CAST_FPEXT : return Instruction::FPExt;
case bitc::CAST_PTRTOADDR: return Instruction::PtrToAddr;
case bitc::CAST_PTRTOINT: return Instruction::PtrToInt;
case bitc::CAST_INTTOPTR: return Instruction::IntToPtr;
case bitc::CAST_BITCAST : return Instruction::BitCast;

View File

@ -647,6 +647,7 @@ static unsigned getEncodedCastOpcode(unsigned Opcode) {
case Instruction::SIToFP : return bitc::CAST_SITOFP;
case Instruction::FPTrunc : return bitc::CAST_FPTRUNC;
case Instruction::FPExt : return bitc::CAST_FPEXT;
case Instruction::PtrToAddr: return bitc::CAST_PTRTOADDR;
case Instruction::PtrToInt: return bitc::CAST_PTRTOINT;
case Instruction::IntToPtr: return bitc::CAST_INTTOPTR;
case Instruction::BitCast : return bitc::CAST_BITCAST;

View File

@ -3657,6 +3657,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV,
break; // Error
}
case Instruction::PtrToAddr:
case Instruction::PtrToInt: {
const DataLayout &DL = getDataLayout();

View File

@ -3977,6 +3977,11 @@ void SelectionDAGBuilder::visitSIToFP(const User &I) {
setValue(&I, DAG.getNode(ISD::SINT_TO_FP, getCurSDLoc(), DestVT, N));
}
void SelectionDAGBuilder::visitPtrToAddr(const User &I) {
// FIXME: this is not correct for pointers with addr width != pointer width
visitPtrToInt(I);
}
void SelectionDAGBuilder::visitPtrToInt(const User &I) {
// What to do depends on the size of the integer and the size of the pointer.
// We can either truncate, zero extend, or no-op, accordingly.

View File

@ -574,6 +574,7 @@ private:
void visitFPToSI(const User &I);
void visitUIToFP(const User &I);
void visitSIToFP(const User &I);
void visitPtrToAddr(const User &I);
void visitPtrToInt(const User &I);
void visitIntToPtr(const User &I);
void visitBitCast(const User &I);

View File

@ -1893,6 +1893,7 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
case SIToFP: return ISD::SINT_TO_FP;
case FPTrunc: return ISD::FP_ROUND;
case FPExt: return ISD::FP_EXTEND;
case PtrToAddr: return ISD::BITCAST;
case PtrToInt: return ISD::BITCAST;
case IntToPtr: return ISD::BITCAST;
case BitCast: return ISD::BITCAST;

View File

@ -254,6 +254,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
return FoldBitCast(V, DestTy);
case Instruction::AddrSpaceCast:
case Instruction::IntToPtr:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
return nullptr;
}

View File

@ -829,6 +829,7 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp,
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::IntToPtr:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::AddrSpaceCast:
// Conservatively return getFull set.

View File

@ -1567,6 +1567,7 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
@ -2223,6 +2224,8 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty,
llvm_unreachable("Invalid cast opcode");
case Instruction::Trunc:
return getTrunc(C, Ty, OnlyIfReduced);
case Instruction::PtrToAddr:
return getPtrToAddr(C, Ty, OnlyIfReduced);
case Instruction::PtrToInt:
return getPtrToInt(C, Ty, OnlyIfReduced);
case Instruction::IntToPtr:
@ -2280,6 +2283,20 @@ Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) {
return getFoldedCast(Instruction::Trunc, C, Ty, OnlyIfReduced);
}
Constant *ConstantExpr::getPtrToAddr(Constant *C, Type *DstTy,
bool OnlyIfReduced) {
assert(C->getType()->isPtrOrPtrVectorTy() &&
"PtrToAddr source must be pointer or pointer vector");
assert(DstTy->isIntOrIntVectorTy() &&
"PtrToAddr destination must be integer or integer vector");
assert(isa<VectorType>(C->getType()) == isa<VectorType>(DstTy));
if (isa<VectorType>(C->getType()))
assert(cast<VectorType>(C->getType())->getElementCount() ==
cast<VectorType>(DstTy)->getElementCount() &&
"Invalid cast between a different number of vector elements");
return getFoldedCast(Instruction::PtrToAddr, C, DstTy, OnlyIfReduced);
}
Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy,
bool OnlyIfReduced) {
assert(C->getType()->isPtrOrPtrVectorTy() &&
@ -2435,6 +2452,7 @@ bool ConstantExpr::isDesirableCastOp(unsigned Opcode) {
case Instruction::FPToSI:
return false;
case Instruction::Trunc:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
@ -2457,6 +2475,7 @@ bool ConstantExpr::isSupportedCastOp(unsigned Opcode) {
case Instruction::FPToSI:
return false;
case Instruction::Trunc:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
@ -3401,6 +3420,7 @@ Instruction *ConstantExpr::getAsInstruction() const {
switch (getOpcode()) {
case Instruction::Trunc:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:

View File

@ -404,6 +404,7 @@ findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases,
return findBaseObject(CE->getOperand(0), Aliases, Op);
}
case Instruction::IntToPtr:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::BitCast:
case Instruction::GetElementPtr:

View File

@ -817,6 +817,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case UIToFP: return "uitofp";
case SIToFP: return "sitofp";
case IntToPtr: return "inttoptr";
case PtrToAddr: return "ptrtoaddr";
case PtrToInt: return "ptrtoint";
case BitCast: return "bitcast";
case AddrSpaceCast: return "addrspacecast";

View File

@ -2798,6 +2798,7 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode,
return false;
case Instruction::BitCast:
return true; // BitCast never modifies bits.
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
return DL.getIntPtrType(SrcTy)->getScalarSizeInBits() ==
DestTy->getScalarSizeInBits();
@ -2855,26 +2856,29 @@ unsigned CastInst::isEliminableCastPair(
// same reason.
const unsigned numCastOps =
Instruction::CastOpsEnd - Instruction::CastOpsBegin;
// clang-format off
static const uint8_t CastResults[numCastOps][numCastOps] = {
// T F F U S F F P I B A -+
// R Z S P P I I T P 2 N T S |
// U E E 2 2 2 2 R E I T C C +- secondOp
// N X X U S F F N X N 2 V V |
// C T T I I P P C T T P T T -+
{ 1, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // Trunc -+
{ 8, 1, 9,99,99, 2,17,99,99,99, 2, 3, 0}, // ZExt |
{ 8, 0, 1,99,99, 0, 2,99,99,99, 0, 3, 0}, // SExt |
{ 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToUI |
{ 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToSI |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // UIToFP +- firstOp
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // SIToFP |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // FPTrunc |
{ 99,99,99, 2, 2,99,99, 8, 2,99,99, 4, 0}, // FPExt |
{ 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3, 0}, // PtrToInt |
{ 99,99,99,99,99,99,99,99,99,11,99,15, 0}, // IntToPtr |
{ 5, 5, 5, 0, 0, 5, 5, 0, 0,16, 5, 1,14}, // BitCast |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12}, // AddrSpaceCast -+
// T F F U S F F P P I B A -+
// R Z S P P I I T P 2 2 N T S |
// U E E 2 2 2 2 R E I A T C C +- secondOp
// N X X U S F F N X N D 2 V V |
// C T T I I P P C T T R P T T -+
{ 1, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // Trunc -+
{ 8, 1, 9,99,99, 2,17,99,99,99,99, 2, 3, 0}, // ZExt |
{ 8, 0, 1,99,99, 0, 2,99,99,99,99, 0, 3, 0}, // SExt |
{ 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // FPToUI |
{ 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // FPToSI |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // UIToFP +- firstOp
{ 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // SIToFP |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // FPTrunc |
{ 99,99,99, 2, 2,99,99, 8, 2,99,99,99, 4, 0}, // FPExt |
{ 1, 0, 0,99,99, 0, 0,99,99,99,99, 7, 3, 0}, // PtrToInt |
{ 1, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // PtrToAddr |
{ 99,99,99,99,99,99,99,99,99,11,99,99,15, 0}, // IntToPtr |
{ 5, 5, 5, 0, 0, 5, 5, 0, 0,16,16, 5, 1,14}, // BitCast |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12}, // AddrSpaceCast -+
};
// clang-format on
// TODO: This logic could be encoded into the table above and handled in the
// switch below.
@ -3046,6 +3050,7 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
case SIToFP: return new SIToFPInst (S, Ty, Name, InsertBefore);
case FPToUI: return new FPToUIInst (S, Ty, Name, InsertBefore);
case FPToSI: return new FPToSIInst (S, Ty, Name, InsertBefore);
case PtrToAddr: return new PtrToAddrInst (S, Ty, Name, InsertBefore);
case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertBefore);
case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertBefore);
case BitCast:
@ -3347,6 +3352,7 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
case Instruction::FPToSI:
return SrcTy->isFPOrFPVectorTy() && DstTy->isIntOrIntVectorTy() &&
SrcEC == DstEC;
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
if (SrcEC != DstEC)
return false;
@ -3460,6 +3466,12 @@ PtrToIntInst::PtrToIntInst(Value *S, Type *Ty, const Twine &Name,
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt");
}
PtrToAddrInst::PtrToAddrInst(Value *S, Type *Ty, const Twine &Name,
InsertPosition InsertBefore)
: CastInst(Ty, PtrToAddr, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToAddr");
}
IntToPtrInst::IntToPtrInst(Value *S, Type *Ty, const Twine &Name,
InsertPosition InsertBefore)
: CastInst(Ty, IntToPtr, S, Name, InsertBefore) {
@ -4427,6 +4439,10 @@ PtrToIntInst *PtrToIntInst::cloneImpl() const {
return new PtrToIntInst(getOperand(0), getType());
}
PtrToAddrInst *PtrToAddrInst::cloneImpl() const {
return new PtrToAddrInst(getOperand(0), getType());
}
IntToPtrInst *IntToPtrInst::cloneImpl() const {
return new IntToPtrInst(getOperand(0), getType());
}

View File

@ -566,6 +566,8 @@ private:
void visitUIToFPInst(UIToFPInst &I);
void visitSIToFPInst(SIToFPInst &I);
void visitIntToPtrInst(IntToPtrInst &I);
void checkPtrToAddr(Type *SrcTy, Type *DestTy, const Value &V);
void visitPtrToAddrInst(PtrToAddrInst &I);
void visitPtrToIntInst(PtrToIntInst &I);
void visitBitCastInst(BitCastInst &I);
void visitAddrSpaceCastInst(AddrSpaceCastInst &I);
@ -834,6 +836,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
&GV);
Check(GV.getInitializer()->getType()->isSized(),
"Global variable initializer must be sized", &GV);
visitConstantExprsRecursively(GV.getInitializer());
// If the global has common linkage, it must have a zero initializer and
// cannot be constant.
if (GV.hasCommonLinkage()) {
@ -2610,6 +2613,8 @@ void Verifier::visitConstantExpr(const ConstantExpr *CE) {
Check(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),
CE->getType()),
"Invalid bitcast", CE);
else if (CE->getOpcode() == Instruction::PtrToAddr)
checkPtrToAddr(CE->getOperand(0)->getType(), CE->getType(), *CE);
}
void Verifier::visitConstantPtrAuth(const ConstantPtrAuth *CPA) {
@ -3532,6 +3537,28 @@ void Verifier::visitFPToSIInst(FPToSIInst &I) {
visitInstruction(I);
}
void Verifier::checkPtrToAddr(Type *SrcTy, Type *DestTy, const Value &V) {
Check(SrcTy->isPtrOrPtrVectorTy(), "PtrToAddr source must be pointer", V);
Check(DestTy->isIntOrIntVectorTy(), "PtrToAddr result must be integral", V);
Check(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToAddr type mismatch",
V);
if (SrcTy->isVectorTy()) {
auto *VSrc = cast<VectorType>(SrcTy);
auto *VDest = cast<VectorType>(DestTy);
Check(VSrc->getElementCount() == VDest->getElementCount(),
"PtrToAddr vector length mismatch", V);
}
Type *AddrTy = DL.getAddressType(SrcTy);
Check(AddrTy == DestTy, "PtrToAddr result must be address width", V);
}
void Verifier::visitPtrToAddrInst(PtrToAddrInst &I) {
checkPtrToAddr(I.getOperand(0)->getType(), I.getType(), I);
visitInstruction(I);
}
void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
// Get the source and destination types
Type *SrcTy = I.getOperand(0)->getType();
@ -3547,7 +3574,7 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
auto *VSrc = cast<VectorType>(SrcTy);
auto *VDest = cast<VectorType>(DestTy);
Check(VSrc->getElementCount() == VDest->getElementCount(),
"PtrToInt Vector width mismatch", &I);
"PtrToInt Vector length mismatch", &I);
}
visitInstruction(I);
@ -3567,7 +3594,7 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
auto *VSrc = cast<VectorType>(SrcTy);
auto *VDest = cast<VectorType>(DestTy);
Check(VSrc->getElementCount() == VDest->getElementCount(),
"IntToPtr Vector width mismatch", &I);
"IntToPtr Vector length mismatch", &I);
}
visitInstruction(I);
}

View File

@ -256,6 +256,7 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
case llvm::Instruction::FPToUI:
case llvm::Instruction::FPToSI:
case llvm::Instruction::FPExt:
case llvm::Instruction::PtrToAddr:
case llvm::Instruction::PtrToInt:
case llvm::Instruction::IntToPtr:
case llvm::Instruction::SIToFP:

View File

@ -1007,6 +1007,9 @@ static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) {
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToSI);
case Instruction::Opcode::FPExt:
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPExt);
case Instruction::Opcode::PtrToAddr:
return static_cast<llvm::Instruction::CastOps>(
llvm::Instruction::PtrToAddr);
case Instruction::Opcode::PtrToInt:
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::PtrToInt);
case Instruction::Opcode::IntToPtr:

View File

@ -263,6 +263,7 @@ static bool isUniformShape(Value *V) {
case llvm::Instruction::FPExt:
return true;
case llvm::Instruction::AddrSpaceCast:
case CastInst::PtrToAddr:
case CastInst::PtrToInt:
case CastInst::IntToPtr:
return false;

View File

@ -81,6 +81,7 @@ LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(
case Instruction::Opcode::FPToUI:
case Instruction::Opcode::FPToSI:
case Instruction::Opcode::FPExt:
case Instruction::Opcode::PtrToAddr:
case Instruction::Opcode::PtrToInt:
case Instruction::Opcode::IntToPtr:
case Instruction::Opcode::SIToFP:

View File

@ -47,6 +47,7 @@
"FPTrunc": [89, 90],
"FPExt": [91, 92],
"PtrToInt": [93, 94],
"PtrToAddr": [135, 136],
"IntToPtr": [95, 96],
"BitCast": [97, 98],
"AddrSpaceCast": [99, 100],

View File

@ -45,6 +45,7 @@ Key: SIToFP: [ 87.00 88.00 ]
Key: FPTrunc: [ 89.00 90.00 ]
Key: FPExt: [ 91.00 92.00 ]
Key: PtrToInt: [ 93.00 94.00 ]
Key: PtrToAddr: [ 135.00 136.00 ]
Key: IntToPtr: [ 95.00 96.00 ]
Key: BitCast: [ 97.00 98.00 ]
Key: AddrSpaceCast: [ 99.00 100.00 ]

View File

@ -45,6 +45,7 @@ Key: SIToFP: [ 43.50 44.00 ]
Key: FPTrunc: [ 44.50 45.00 ]
Key: FPExt: [ 45.50 46.00 ]
Key: PtrToInt: [ 46.50 47.00 ]
Key: PtrToAddr: [ 67.50 68.00 ]
Key: IntToPtr: [ 47.50 48.00 ]
Key: BitCast: [ 48.50 49.00 ]
Key: AddrSpaceCast: [ 49.50 50.00 ]

View File

@ -45,6 +45,7 @@ Key: SIToFP: [ 8.70 8.80 ]
Key: FPTrunc: [ 8.90 9.00 ]
Key: FPExt: [ 9.10 9.20 ]
Key: PtrToInt: [ 9.30 9.40 ]
Key: PtrToAddr: [ 13.50 13.60 ]
Key: IntToPtr: [ 9.50 9.60 ]
Key: BitCast: [ 9.70 9.80 ]
Key: AddrSpaceCast: [ 9.90 10.00 ]

View File

@ -0,0 +1,56 @@
;; Check all requirements on the ptrtoaddr constant expression operands
;; Most of these invalid cases are detected at parse time but some are only
;; detected at verification time (see Verifier::visitPtrToAddrInst())
; RUN: rm -rf %t && split-file --leading-lines %s %t
;--- src_vec_dst_no_vec.ll
; RUN: not llvm-as %t/src_vec_dst_no_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_VEC_DST_NO_VEC %s --implicit-check-not="error:"
@g = global i64 ptrtoaddr (<2 x ptr> <ptr @g, ptr @g> to i64)
; SRC_VEC_DST_NO_VEC: [[#@LINE-1]]:17: error: invalid cast opcode for cast from '<2 x ptr>' to 'i64'
;--- src_no_vec_dst_vec.ll
; RUN: not llvm-as %t/src_no_vec_dst_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_NO_VEC_DST_VEC %s --implicit-check-not="error:"
@g = global <2 x i64> ptrtoaddr (ptr @g to <2 x i64>)
; SRC_NO_VEC_DST_VEC: [[#@LINE-1]]:23: error: invalid cast opcode for cast from 'ptr' to '<2 x i64>'
;--- dst_not_int.ll
; RUN: not llvm-as %t/dst_not_int.ll -o /dev/null 2>&1 | FileCheck -check-prefix=DST_NOT_INT %s --implicit-check-not="error:"
@g = global float ptrtoaddr (ptr @g to float)
; DST_NOT_INT: [[#@LINE-1]]:19: error: invalid cast opcode for cast from 'ptr' to 'float'
;--- dst_not_int_vec.ll
; RUN: not llvm-as %t/dst_not_int_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=DST_NOT_INT_VEC %s --implicit-check-not="error:"
@g = global <2 x float> ptrtoaddr (<2 x ptr> <ptr @g, ptr @g> to <2 x float>)
; DST_NOT_INT_VEC: [[#@LINE-1]]:25: error: invalid cast opcode for cast from '<2 x ptr>' to '<2 x float>'
;--- src_not_ptr.ll
; RUN: not llvm-as %t/src_not_ptr.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_NOT_PTR %s --implicit-check-not="error:"
@g = global i64 ptrtoaddr (i32 1 to i64)
; SRC_NOT_PTR: [[#@LINE-1]]:17: error: invalid cast opcode for cast from 'i32' to 'i64'
;--- src_not_ptr_vec.ll
; RUN: not llvm-as %t/src_not_ptr_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_NOT_PTR_VEC %s --implicit-check-not="error:"
@g = global <2 x i64> ptrtoaddr (<2 x i32> <i32 1, i32 2> to <2 x i64>)
; SRC_NOT_PTR_VEC: [[#@LINE-1]]:23: error: invalid cast opcode for cast from '<2 x i32>' to '<2 x i64>'
;--- vec_src_fewer_elems.ll
; RUN: not llvm-as %t/vec_src_fewer_elems.ll -o /dev/null 2>&1 | FileCheck -check-prefix=VEC_SRC_FEWER_ELEMS %s --implicit-check-not="error:"
@g = global <4 x i64> ptrtoaddr (<2 x ptr> <ptr @g, ptr @g> to <4 x i64>)
; VEC_SRC_FEWER_ELEMS: [[#@LINE-1]]:23: error: invalid cast opcode for cast from '<2 x ptr>' to '<4 x i64>'
;--- vec_dst_fewer_elems.ll
; RUN: not llvm-as %t/vec_dst_fewer_elems.ll -o /dev/null 2>&1 | FileCheck -check-prefix=VEC_DST_FEWER_ELEMS %s --implicit-check-not="error:"
@g = global <2 x i64> ptrtoaddr (<4 x ptr> <ptr @g, ptr @g, ptr @g, ptr @g> to <2 x i64>)
; VEC_DST_FEWER_ELEMS: [[#@LINE-1]]:23: error: invalid cast opcode for cast from '<4 x ptr>' to '<2 x i64>'
;--- dst_not_addr_size.ll
; The following invalid IR is caught by the verifier, not the parser:
; RUN: llvm-as %t/dst_not_addr_size.ll --disable-output --disable-verify
; RUN: not llvm-as %t/dst_not_addr_size.ll -o /dev/null 2>&1 | FileCheck -check-prefix=DST_NOT_ADDR_SIZE %s --implicit-check-not="error:"
; DST_NOT_ADDR_SIZE: assembly parsed, but does not verify as correct!
@g = global i32 ptrtoaddr (ptr @g to i32)
; DST_NOT_ADDR_SIZE-NEXT: PtrToAddr result must be address width
; DST_NOT_ADDR_SIZE-NEXT: i32 ptrtoaddr (ptr @g to i32)
@g_vec = global <4 x i32> ptrtoaddr (<4 x ptr> <ptr @g, ptr @g, ptr @g, ptr @g> to <4 x i32>)
; TODO: Verifier.cpp does not visit ConstantVector/ConstantStruct values
; TODO-DST_NOT_ADDR_SIZE: PtrToAddr result must be address width

View File

@ -0,0 +1,84 @@
;; Check all requirements on the ptrtoaddr instruction operands
;; Most of these invalid cases are detected at parse time but some are only
;; detected at verification time (see Verifier::visitPtrToAddrInst())
; RUN: rm -rf %t && split-file --leading-lines %s %t
;--- src_vec_dst_no_vec.ll
; RUN: not llvm-as %t/src_vec_dst_no_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_VEC_DST_NO_VEC %s --implicit-check-not="error:"
define i64 @bad(<2 x ptr> %p) {
%addr = ptrtoaddr <2 x ptr> %p to i64
; SRC_VEC_DST_NO_VEC: [[#@LINE-1]]:21: error: invalid cast opcode for cast from '<2 x ptr>' to 'i64'
ret i64 %addr
}
;--- src_no_vec_dst_vec.ll
; RUN: not llvm-as %t/src_no_vec_dst_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_NO_VEC_DST_VEC %s --implicit-check-not="error:"
define <2 x i64> @bad(ptr %p) {
%addr = ptrtoaddr ptr %p to <2 x i64>
; SRC_NO_VEC_DST_VEC: [[#@LINE-1]]:21: error: invalid cast opcode for cast from 'ptr' to '<2 x i64>'
ret <2 x i64> %addr
}
;--- dst_not_int.ll
; RUN: not llvm-as %t/dst_not_int.ll -o /dev/null 2>&1 | FileCheck -check-prefix=DST_NOT_INT %s --implicit-check-not="error:"
define float @bad(ptr %p) {
%addr = ptrtoaddr ptr %p to float
; DST_NOT_INT: [[#@LINE-1]]:21: error: invalid cast opcode for cast from 'ptr' to 'float'
ret float %addr
}
;--- dst_not_int_vec.ll
; RUN: not llvm-as %t/dst_not_int_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=DST_NOT_INT_VEC %s --implicit-check-not="error:"
define <2 x float> @bad(<2 x ptr> %p) {
%addr = ptrtoaddr <2 x ptr> %p to <2 x float>
; DST_NOT_INT_VEC: [[#@LINE-1]]:21: error: invalid cast opcode for cast from '<2 x ptr>' to '<2 x float>'
ret <2 x float> %addr
}
;--- src_not_ptr.ll
; RUN: not llvm-as %t/src_not_ptr.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_NOT_PTR %s --implicit-check-not="error:"
define i64 @bad(i32 %p) {
%addr = ptrtoaddr i32 %p to i64
; SRC_NOT_PTR: [[#@LINE-1]]:21: error: invalid cast opcode for cast from 'i32' to 'i64'
ret i64 %addr
}
;--- src_not_ptr_vec.ll
; RUN: not llvm-as %t/src_not_ptr_vec.ll -o /dev/null 2>&1 | FileCheck -check-prefix=SRC_NOT_PTR_VEC %s --implicit-check-not="error:"
define <2 x i64> @bad(<2 x i32> %p) {
%addr = ptrtoaddr <2 x i32> %p to <2 x i64>
; SRC_NOT_PTR_VEC: [[#@LINE-1]]:21: error: invalid cast opcode for cast from '<2 x i32>' to '<2 x i64>'
ret <2 x i64> %addr
}
;--- vec_src_fewer_elems.ll
; RUN: not llvm-as %t/vec_src_fewer_elems.ll -o /dev/null 2>&1 | FileCheck -check-prefix=VEC_SRC_FEWER_ELEMS %s --implicit-check-not="error:"
define <4 x i64> @bad(<2 x ptr> %p) {
%addr = ptrtoaddr <2 x ptr> %p to <4 x i64>
; VEC_SRC_FEWER_ELEMS: [[#@LINE-1]]:21: error: invalid cast opcode for cast from '<2 x ptr>' to '<4 x i64>'
ret <4 x i64> %addr
}
;--- vec_dst_fewer_elems.ll
; RUN: not llvm-as %t/vec_dst_fewer_elems.ll -o /dev/null 2>&1 | FileCheck -check-prefix=VEC_DST_FEWER_ELEMS %s --implicit-check-not="error:"
define <2 x i64> @bad(<4 x ptr> %p) {
%addr = ptrtoaddr <4 x ptr> %p to <2 x i64>
; VEC_DST_FEWER_ELEMS: [[#@LINE-1]]:21: error: invalid cast opcode for cast from '<4 x ptr>' to '<2 x i64>'
ret <2 x i64> %addr
}
;--- dst_not_addr_size.ll
; The following invalid IR is caught by the verifier, not the parser:
; RUN: llvm-as %t/dst_not_addr_size.ll --disable-output --disable-verify
; RUN: not llvm-as %t/dst_not_addr_size.ll -o /dev/null 2>&1 | FileCheck -check-prefix=DST_NOT_ADDR_SIZE %s --implicit-check-not="error:"
; DST_NOT_ADDR_SIZE: assembly parsed, but does not verify as correct!
define i32 @bad(ptr %p) {
%addr = ptrtoaddr ptr %p to i32
; DST_NOT_ADDR_SIZE: PtrToAddr result must be address width
ret i32 %addr
}
define <4 x i32> @bad_vec(<4 x ptr> %p) {
%addr = ptrtoaddr <4 x ptr> %p to <4 x i32>
; DST_NOT_ADDR_SIZE: PtrToAddr result must be address width
ret <4 x i32> %addr
}

View File

@ -0,0 +1,27 @@
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
target datalayout = "p1:64:64:64:32"
@i_as0 = global i32 0
@global_cast_as0 = global i64 ptrtoaddr (ptr @i_as0 to i64)
; CHECK: @global_cast_as0 = global i64 ptrtoaddr (ptr @i_as0 to i64)
@i_as1 = addrspace(1) global i32 0
@global_cast_as1 = global i32 ptrtoaddr (ptr addrspace(1) @i_as1 to i32)
; CHECK: @global_cast_as1 = global i32 ptrtoaddr (ptr addrspace(1) @i_as1 to i32)
define i64 @test_as0(ptr %p) {
%addr = ptrtoaddr ptr %p to i64
; CHECK: %addr = ptrtoaddr ptr %p to i64
ret i64 %addr
}
define i32 @test_as1(ptr addrspace(1) %p) {
%addr = ptrtoaddr ptr addrspace(1) %p to i32
; CHECK: %addr = ptrtoaddr ptr addrspace(1) %p to i32
ret i32 %addr
}
define <2 x i32> @test_vec_as1(<2 x ptr addrspace(1)> %p) {
%addr = ptrtoaddr <2 x ptr addrspace(1)> %p to <2 x i32>
; CHECK: %addr = ptrtoaddr <2 x ptr addrspace(1)> %p to <2 x i32>
ret <2 x i32> %addr
}

View File

@ -0,0 +1,27 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
target datalayout = "p1:64:64:64:32"
@i_as0 = global i32 0
@global_cast_as0 = global i64 ptrtoaddr (ptr @i_as0 to i64)
; CHECK: @global_cast_as0 = global i64 ptrtoaddr (ptr @i_as0 to i64)
@i_as1 = addrspace(1) global i32 0
@global_cast_as1 = global i32 ptrtoaddr (ptr addrspace(1) @i_as1 to i32)
; CHECK: @global_cast_as1 = global i32 ptrtoaddr (ptr addrspace(1) @i_as1 to i32)
define i64 @test_as0(ptr %p) {
%addr = ptrtoaddr ptr %p to i64
; CHECK: %addr = ptrtoaddr ptr %p to i64
ret i64 %addr
}
define i32 @test_as1(ptr addrspace(1) %p) {
%addr = ptrtoaddr ptr addrspace(1) %p to i32
; CHECK: %addr = ptrtoaddr ptr addrspace(1) %p to i32
ret i32 %addr
}
define <2 x i32> @test_vec_as1(<2 x ptr addrspace(1)> %p) {
%addr = ptrtoaddr <2 x ptr addrspace(1)> %p to <2 x i32>
; CHECK: %addr = ptrtoaddr <2 x ptr addrspace(1)> %p to <2 x i32>
ret <2 x i32> %addr
}

View File

@ -0,0 +1,109 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=CHECK
define i1 @ptrtoaddr_1(ptr %p) {
; CHECK-LABEL: ptrtoaddr_1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: xorb $1, %al
; CHECK-NEXT: # kill: def $al killed $al killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i1
%ret = xor i1 %trunc, 1
ret i1 %ret
}
define i8 @ptrtoaddr_8(ptr %p) {
; CHECK-LABEL: ptrtoaddr_8:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notb %al
; CHECK-NEXT: # kill: def $al killed $al killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i8
%ret = xor i8 %trunc, -1
ret i8 %ret
}
define i16 @ptrtoaddr_16(ptr %p) {
; CHECK-LABEL: ptrtoaddr_16:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notw %ax
; CHECK-NEXT: # kill: def $ax killed $ax killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i16
%ret = xor i16 %trunc, -1
ret i16 %ret
}
define i32 @ptrtoaddr_32(ptr %p) {
; CHECK-LABEL: ptrtoaddr_32:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notl %eax
; CHECK-NEXT: # kill: def $eax killed $eax killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i32
%ret = xor i32 %trunc, -1
ret i32 %ret
}
define i64 @ptrtoaddr_64(ptr %p) {
; CHECK-LABEL: ptrtoaddr_64:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notq %rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%ret = xor i64 %addr, -1
ret i64 %ret
}
define i128 @ptrtoaddr_128(ptr %p) {
; CHECK-LABEL: ptrtoaddr_128:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: notq %rax
; CHECK-NEXT: notq %rdx
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%ext = zext i64 %addr to i128
%ret = xor i128 %ext, -1
ret i128 %ret
}
; TODO: Vector version cannot be handled by GlobalIsel yet (same error as ptrtoint: https://github.com/llvm/llvm-project/issues/150875).
; define <2 x i64> @ptrtoaddr_vec(<2 x ptr> %p) {
; entry:
; %addr = ptrtoaddr <2 x ptr> %p to <2 x i64>
; %ret = xor <2 x i64> %addr, <i64 -1, i64 -1>
; ret <2 x i64> %ret
;}
; UTC_ARGS: --disable
@foo = global [16 x i8] zeroinitializer
@addr = global i64 ptrtoaddr (ptr @foo to i64)
; CHECK: addr:
; CHECK-NEXT: .quad foo
; CHECK-NEXT: .size addr, 8
@addr_plus_one = global i64 ptrtoaddr (ptr getelementptr (i8, ptr @foo, i64 1) to i64)
; CHECK: addr_plus_one:
; CHECK-NEXT: .quad foo+1
; CHECK-NEXT: .size addr_plus_one, 8
@const_addr = global i64 ptrtoaddr (ptr getelementptr (i8, ptr null, i64 1) to i64)
; CHECK: const_addr:
; CHECK-NEXT: .quad 0+1
; CHECK-NEXT: .size const_addr, 8

View File

@ -0,0 +1,113 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-linux-gnu < %s -o - | FileCheck %s --check-prefix=CHECK
define i1 @ptrtoaddr_1(ptr %p) {
; CHECK-LABEL: ptrtoaddr_1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: xorb $1, %al
; CHECK-NEXT: # kill: def $al killed $al killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i1
%ret = xor i1 %trunc, 1
ret i1 %ret
}
define i8 @ptrtoaddr_8(ptr %p) {
; CHECK-LABEL: ptrtoaddr_8:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notb %al
; CHECK-NEXT: # kill: def $al killed $al killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i8
%ret = xor i8 %trunc, -1
ret i8 %ret
}
define i16 @ptrtoaddr_16(ptr %p) {
; CHECK-LABEL: ptrtoaddr_16:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notl %eax
; CHECK-NEXT: # kill: def $ax killed $ax killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i16
%ret = xor i16 %trunc, -1
ret i16 %ret
}
define i32 @ptrtoaddr_32(ptr %p) {
; CHECK-LABEL: ptrtoaddr_32:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notl %eax
; CHECK-NEXT: # kill: def $eax killed $eax killed $rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%trunc = trunc i64 %addr to i32
%ret = xor i32 %trunc, -1
ret i32 %ret
}
define i64 @ptrtoaddr_64(ptr %p) {
; CHECK-LABEL: ptrtoaddr_64:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notq %rax
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%ret = xor i64 %addr, -1
ret i64 %ret
}
define i128 @ptrtoaddr_128(ptr %p) {
; CHECK-LABEL: ptrtoaddr_128:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: notq %rax
; CHECK-NEXT: movq $-1, %rdx
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr ptr %p to i64
%ext = zext i64 %addr to i128
%ret = xor i128 %ext, -1
ret i128 %ret
}
define <2 x i64> @ptrtoaddr_vec(<2 x ptr> %p) {
; CHECK-LABEL: ptrtoaddr_vec:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pcmpeqd %xmm1, %xmm1
; CHECK-NEXT: pxor %xmm1, %xmm0
; CHECK-NEXT: retq
entry:
%addr = ptrtoaddr <2 x ptr> %p to <2 x i64>
%ret = xor <2 x i64> %addr, <i64 -1, i64 -1>
ret <2 x i64> %ret
}
; UTC_ARGS: --disable
@foo = global [16 x i8] zeroinitializer
@addr = global i64 ptrtoaddr (ptr @foo to i64)
; CHECK: addr:
; CHECK-NEXT: .quad foo
; CHECK-NEXT: .size addr, 8
@addr_plus_one = global i64 ptrtoaddr (ptr getelementptr (i8, ptr @foo, i64 1) to i64)
; CHECK: addr_plus_one:
; CHECK-NEXT: .quad foo+1
; CHECK-NEXT: .size addr_plus_one, 8
@const_addr = global i64 ptrtoaddr (ptr getelementptr (i8, ptr null, i64 1) to i64)
; CHECK: const_addr:
; CHECK-NEXT: .quad 0+1
; CHECK-NEXT: .size const_addr, 8

View File

@ -7,9 +7,9 @@ define i32 @nested(i32 %src) #0 {
; CHECK-SAME: i32 [[A0:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[BB15160:.*:]]
; CHECK-NEXT: [[T1:%.*]] = call token @llvm.experimental.convergence.entry()
; CHECK-NEXT: %"vl77672llvm.experimental.convergence.anchor()" = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: %"op68297(vl77672)" = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token %"vl77672llvm.experimental.convergence.anchor()") ]
; CHECK-NEXT: ret i32 %"op68297(vl77672)"
; CHECK-NEXT: %"vl14659llvm.experimental.convergence.anchor()" = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: %"op15516(vl14659)" = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token %"vl14659llvm.experimental.convergence.anchor()") ]
; CHECK-NEXT: ret i32 %"op15516(vl14659)"
;
%t1 = call token @llvm.experimental.convergence.entry()
%t2 = call token @llvm.experimental.convergence.anchor()

View File

@ -8,18 +8,18 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"vl72693([[A1]], 1)" = add i32 [[A1]], 1
; CHECK-NEXT: br label %[[BB16110:.*]]
; CHECK: [[BB16110]]:
; CHECK-NEXT: %"op10912(op18080, vl72693)" = phi i32 [ %"op18080(op10412, op17645)", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
; CHECK-NEXT: %"op10912(op17645, vl72693)" = phi i32 [ %"op17645(op10912)70", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
; CHECK-NEXT: %"op15084(op10912)" = mul i32 %"op10912(op18080, vl72693)", undef
; CHECK-NEXT: %"op16562(op15084)" = xor i32 -1, %"op15084(op10912)"
; CHECK-NEXT: %"op44627(op10912, op16562)" = add i32 %"op10912(op18080, vl72693)", %"op16562(op15084)"
; CHECK-NEXT: %"op17645(op10912)" = add i32 -1, %"op10912(op17645, vl72693)"
; CHECK-NEXT: %"op18080(op17645, op44627)" = add i32 %"op17645(op10912)", %"op44627(op10912, op16562)"
; CHECK-NEXT: %"op17720(op15084, op18080)" = mul i32 %"op15084(op10912)", %"op18080(op17645, op44627)"
; CHECK-NEXT: %"op16562(op17720)" = xor i32 -1, %"op17720(op15084, op18080)"
; CHECK-NEXT: %"op17430(op16562, op18080)" = add i32 %"op16562(op17720)", %"op18080(op17645, op44627)"
; CHECK-NEXT: %"op81283(op18080, vl72693)" = phi i32 [ %"op18080(op10412, op18131)", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
; CHECK-NEXT: %"op81283(op18131, vl72693)" = phi i32 [ %"op18131(op81283)70", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
; CHECK-NEXT: %"op13219(op81283)" = mul i32 %"op81283(op18080, vl72693)", undef
; CHECK-NEXT: %"op16562(op13219)" = xor i32 -1, %"op13219(op81283)"
; CHECK-NEXT: %"op12556(op16562, op81283)" = add i32 %"op16562(op13219)", %"op81283(op18080, vl72693)"
; CHECK-NEXT: %"op18131(op81283)" = add i32 -1, %"op81283(op18131, vl72693)"
; CHECK-NEXT: %"op18080(op12556, op18131)" = add i32 %"op12556(op16562, op81283)", %"op18131(op81283)"
; CHECK-NEXT: %"op17720(op13219, op18080)" = mul i32 %"op13219(op81283)", %"op18080(op12556, op18131)"
; CHECK-NEXT: %"op16562(op17720)" = xor i32 -1, %"op17720(op13219, op18080)"
; CHECK-NEXT: %"op17430(op16562, op18080)" = add i32 %"op16562(op17720)", %"op18080(op12556, op18131)"
; CHECK-NEXT: %"op10412(op17430)" = add i32 %"op17430(op16562, op18080)", undef
; CHECK-NEXT: %"op17720(op10412, op17720)" = mul i32 %"op10412(op17430)", %"op17720(op15084, op18080)"
; CHECK-NEXT: %"op17720(op10412, op17720)" = mul i32 %"op10412(op17430)", %"op17720(op13219, op18080)"
; CHECK-NEXT: %"op16562(op17720)1" = xor i32 -1, %"op17720(op10412, op17720)"
; CHECK-NEXT: %"op17430(op10412, op16562)" = add i32 %"op10412(op17430)", %"op16562(op17720)1"
; CHECK-NEXT: %"op10412(op17430)2" = add i32 %"op17430(op10412, op16562)", undef
@ -45,11 +45,11 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"op17720(op10412, op17720)21" = mul i32 %"op10412(op17430)20", %"op17720(op10412, op17720)17"
; CHECK-NEXT: %"op16562(op17720)22" = xor i32 -1, %"op17720(op10412, op17720)21"
; CHECK-NEXT: %"op17430(op10412, op16562)23" = add i32 %"op10412(op17430)20", %"op16562(op17720)22"
; CHECK-NEXT: %"op17645(op10912)24" = add i32 -9, %"op10912(op17645, vl72693)"
; CHECK-NEXT: %"op18080(op17430, op17645)" = add i32 %"op17430(op10412, op16562)23", %"op17645(op10912)24"
; CHECK-NEXT: %"op17720(op17720, op18080)" = mul i32 %"op17720(op10412, op17720)21", %"op18080(op17430, op17645)"
; CHECK-NEXT: %"op18131(op81283)24" = add i32 -9, %"op81283(op18131, vl72693)"
; CHECK-NEXT: %"op18080(op17430, op18131)" = add i32 %"op17430(op10412, op16562)23", %"op18131(op81283)24"
; CHECK-NEXT: %"op17720(op17720, op18080)" = mul i32 %"op17720(op10412, op17720)21", %"op18080(op17430, op18131)"
; CHECK-NEXT: %"op16562(op17720)25" = xor i32 -1, %"op17720(op17720, op18080)"
; CHECK-NEXT: %"op17430(op16562, op18080)26" = add i32 %"op16562(op17720)25", %"op18080(op17430, op17645)"
; CHECK-NEXT: %"op17430(op16562, op18080)26" = add i32 %"op16562(op17720)25", %"op18080(op17430, op18131)"
; CHECK-NEXT: %"op10412(op17430)27" = add i32 %"op17430(op16562, op18080)26", undef
; CHECK-NEXT: %"op17720(op10412, op17720)28" = mul i32 %"op10412(op17430)27", %"op17720(op17720, op18080)"
; CHECK-NEXT: %"op16562(op17720)29" = xor i32 -1, %"op17720(op10412, op17720)28"
@ -66,11 +66,11 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"op17720(op10412, op17720)40" = mul i32 %"op10412(op17430)39", %"op17720(op10412, op17720)36"
; CHECK-NEXT: %"op16562(op17720)41" = xor i32 -1, %"op17720(op10412, op17720)40"
; CHECK-NEXT: %"op17430(op10412, op16562)42" = add i32 %"op10412(op17430)39", %"op16562(op17720)41"
; CHECK-NEXT: %"op17645(op10912)43" = add i32 -14, %"op10912(op17645, vl72693)"
; CHECK-NEXT: %"op18080(op17430, op17645)44" = add i32 %"op17430(op10412, op16562)42", %"op17645(op10912)43"
; CHECK-NEXT: %"op17720(op17720, op18080)45" = mul i32 %"op17720(op10412, op17720)40", %"op18080(op17430, op17645)44"
; CHECK-NEXT: %"op18131(op81283)43" = add i32 -14, %"op81283(op18131, vl72693)"
; CHECK-NEXT: %"op18080(op17430, op18131)44" = add i32 %"op17430(op10412, op16562)42", %"op18131(op81283)43"
; CHECK-NEXT: %"op17720(op17720, op18080)45" = mul i32 %"op17720(op10412, op17720)40", %"op18080(op17430, op18131)44"
; CHECK-NEXT: %"op16562(op17720)46" = xor i32 -1, %"op17720(op17720, op18080)45"
; CHECK-NEXT: %"op17430(op16562, op18080)47" = add i32 %"op16562(op17720)46", %"op18080(op17430, op17645)44"
; CHECK-NEXT: %"op17430(op16562, op18080)47" = add i32 %"op16562(op17720)46", %"op18080(op17430, op18131)44"
; CHECK-NEXT: %"op10412(op17430)48" = add i32 %"op17430(op16562, op18080)47", undef
; CHECK-NEXT: %"op17720(op10412, op17720)49" = mul i32 %"op10412(op17430)48", %"op17720(op17720, op18080)45"
; CHECK-NEXT: %"op16562(op17720)50" = xor i32 -1, %"op17720(op10412, op17720)49"
@ -93,9 +93,9 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"op17430(op10412, op16562)67" = add i32 %"op10412(op17430)64", %"op16562(op17720)66"
; CHECK-NEXT: %"op10412(op17430)68" = add i32 %"op17430(op10412, op16562)67", undef
; CHECK-NEXT: %"op10412(op10412)69" = add i32 %"op10412(op17430)68", undef
; CHECK-NEXT: %"op17645(op10912)70" = add i32 -21, %"op10912(op17645, vl72693)"
; CHECK-NEXT: %"op18080(op10412, op17645)" = add i32 %"op10412(op10412)69", %"op17645(op10912)70"
; CHECK-NEXT: store i32 %"op18080(op10412, op17645)", ptr [[A0]], align 4
; CHECK-NEXT: %"op18131(op81283)70" = add i32 -21, %"op81283(op18131, vl72693)"
; CHECK-NEXT: %"op18080(op10412, op18131)" = add i32 %"op10412(op10412)69", %"op18131(op81283)70"
; CHECK-NEXT: store i32 %"op18080(op10412, op18131)", ptr [[A0]], align 4
; CHECK-NEXT: br label %[[BB16110]]
;
bb:

View File

@ -28,16 +28,16 @@ define double @baz(double %x) {
; CHECK-SAME: double [[A0:%.*]]) {
; CHECK-NEXT: [[BB76951:.*:]]
; CHECK-NEXT: [[IFCOND:%.*]] = fcmp one double [[A0]], 0.000000e+00
; CHECK-NEXT: br i1 [[IFCOND]], label %[[BB91455:.*]], label %[[BB914551:.*]]
; CHECK: [[BB91455]]:
; CHECK-NEXT: %"vl15001bir()" = call double @bir()
; CHECK-NEXT: br i1 [[IFCOND]], label %[[BB47054:.*]], label %[[BB470541:.*]]
; CHECK: [[BB47054]]:
; CHECK-NEXT: %"vl16994bir()" = call double @bir()
; CHECK-NEXT: br label %[[BB17254:.*]]
; CHECK: [[BB914551]]:
; CHECK-NEXT: %"vl69719bar()" = call double @bar()
; CHECK: [[BB470541]]:
; CHECK-NEXT: %"vl88592bar()" = call double @bar()
; CHECK-NEXT: br label %[[BB17254]]
; CHECK: [[BB17254]]:
; CHECK-NEXT: %"op19734(vl15001, vl69719)" = phi double [ %"vl15001bir()", %[[BB91455]] ], [ %"vl69719bar()", %[[BB914551]] ]
; CHECK-NEXT: ret double %"op19734(vl15001, vl69719)"
; CHECK-NEXT: %"op16411(vl16994, vl88592)" = phi double [ %"vl16994bir()", %[[BB47054]] ], [ %"vl88592bar()", %[[BB470541]] ]
; CHECK-NEXT: ret double %"op16411(vl16994, vl88592)"
;
entry:
%ifcond = fcmp one double %x, 0.000000e+00

View File

@ -23,7 +23,7 @@ declare void @effecting()
; Place dead instruction(s) before the terminator
define void @call_effecting() {
; CHECK-LABEL: define void @call_effecting() {
; CHECK-NEXT: bb15160:
; CHECK-NEXT: bb14885:
; CHECK-NEXT: call void @effecting()
; CHECK-NEXT: [[TMP0:%.*]] = add i32 0, 1
; CHECK-NEXT: ret void
@ -51,7 +51,7 @@ exit:
define void @dont_move_above_alloca() {
; CHECK-LABEL: define void @dont_move_above_alloca() {
; CHECK-NEXT: bb15160:
; CHECK-NEXT: bb14885:
; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void @effecting()
; CHECK-NEXT: ret void
@ -65,7 +65,7 @@ declare void @effecting1()
define void @dont_reorder_effecting() {
; CHECK-LABEL: define void @dont_reorder_effecting() {
; CHECK-NEXT: bb10075:
; CHECK-NEXT: bb45003:
; CHECK-NEXT: call void @effecting()
; CHECK-NEXT: call void @effecting1()
; CHECK-NEXT: ret void
@ -79,7 +79,7 @@ declare void @effecting2(i32)
define void @dont_reorder_effecting1() {
; CHECK-LABEL: define void @dont_reorder_effecting1() {
; CHECK-NEXT: bb10075:
; CHECK-NEXT: bb45003:
; CHECK-NEXT: [[ONE:%.*]] = add i32 1, 1
; CHECK-NEXT: call void @effecting2(i32 [[ONE]])
; CHECK-NEXT: [[TWO:%.*]] = add i32 2, 2

View File

@ -1,6 +1,6 @@
; RUN: llvm-ir2vec entities | FileCheck %s
CHECK: 92
CHECK: 93
CHECK-NEXT: Ret 0
CHECK-NEXT: Br 1
CHECK-NEXT: Switch 2
@ -48,48 +48,49 @@ CHECK-NEXT: SIToFP 43
CHECK-NEXT: FPTrunc 44
CHECK-NEXT: FPExt 45
CHECK-NEXT: PtrToInt 46
CHECK-NEXT: IntToPtr 47
CHECK-NEXT: BitCast 48
CHECK-NEXT: AddrSpaceCast 49
CHECK-NEXT: CleanupPad 50
CHECK-NEXT: CatchPad 51
CHECK-NEXT: ICmp 52
CHECK-NEXT: FCmp 53
CHECK-NEXT: PHI 54
CHECK-NEXT: Call 55
CHECK-NEXT: Select 56
CHECK-NEXT: UserOp1 57
CHECK-NEXT: UserOp2 58
CHECK-NEXT: VAArg 59
CHECK-NEXT: ExtractElement 60
CHECK-NEXT: InsertElement 61
CHECK-NEXT: ShuffleVector 62
CHECK-NEXT: ExtractValue 63
CHECK-NEXT: InsertValue 64
CHECK-NEXT: LandingPad 65
CHECK-NEXT: Freeze 66
CHECK-NEXT: FloatTy 67
CHECK-NEXT: PtrToAddr 47
CHECK-NEXT: IntToPtr 48
CHECK-NEXT: BitCast 49
CHECK-NEXT: AddrSpaceCast 50
CHECK-NEXT: CleanupPad 51
CHECK-NEXT: CatchPad 52
CHECK-NEXT: ICmp 53
CHECK-NEXT: FCmp 54
CHECK-NEXT: PHI 55
CHECK-NEXT: Call 56
CHECK-NEXT: Select 57
CHECK-NEXT: UserOp1 58
CHECK-NEXT: UserOp2 59
CHECK-NEXT: VAArg 60
CHECK-NEXT: ExtractElement 61
CHECK-NEXT: InsertElement 62
CHECK-NEXT: ShuffleVector 63
CHECK-NEXT: ExtractValue 64
CHECK-NEXT: InsertValue 65
CHECK-NEXT: LandingPad 66
CHECK-NEXT: Freeze 67
CHECK-NEXT: FloatTy 68
CHECK-NEXT: FloatTy 69
CHECK-NEXT: FloatTy 70
CHECK-NEXT: FloatTy 71
CHECK-NEXT: FloatTy 72
CHECK-NEXT: FloatTy 73
CHECK-NEXT: VoidTy 74
CHECK-NEXT: LabelTy 75
CHECK-NEXT: MetadataTy 76
CHECK-NEXT: UnknownTy 77
CHECK-NEXT: TokenTy 78
CHECK-NEXT: IntegerTy 79
CHECK-NEXT: FunctionTy 80
CHECK-NEXT: PointerTy 81
CHECK-NEXT: StructTy 82
CHECK-NEXT: ArrayTy 83
CHECK-NEXT: VectorTy 84
CHECK-NEXT: FloatTy 74
CHECK-NEXT: VoidTy 75
CHECK-NEXT: LabelTy 76
CHECK-NEXT: MetadataTy 77
CHECK-NEXT: UnknownTy 78
CHECK-NEXT: TokenTy 79
CHECK-NEXT: IntegerTy 80
CHECK-NEXT: FunctionTy 81
CHECK-NEXT: PointerTy 82
CHECK-NEXT: StructTy 83
CHECK-NEXT: ArrayTy 84
CHECK-NEXT: VectorTy 85
CHECK-NEXT: PointerTy 86
CHECK-NEXT: UnknownTy 87
CHECK-NEXT: Function 88
CHECK-NEXT: Pointer 89
CHECK-NEXT: Constant 90
CHECK-NEXT: Variable 91
CHECK-NEXT: VectorTy 86
CHECK-NEXT: PointerTy 87
CHECK-NEXT: UnknownTy 88
CHECK-NEXT: Function 89
CHECK-NEXT: Pointer 90
CHECK-NEXT: Constant 91
CHECK-NEXT: Variable 92

View File

@ -25,41 +25,41 @@ entry:
}
; TRIPLETS: MAX_RELATION=3
; TRIPLETS-NEXT: 12 79 0
; TRIPLETS-NEXT: 12 91 2
; TRIPLETS-NEXT: 12 91 3
; TRIPLETS-NEXT: 12 80 0
; TRIPLETS-NEXT: 12 92 2
; TRIPLETS-NEXT: 12 92 3
; TRIPLETS-NEXT: 12 0 1
; TRIPLETS-NEXT: 0 74 0
; TRIPLETS-NEXT: 0 91 2
; TRIPLETS-NEXT: 16 79 0
; TRIPLETS-NEXT: 16 91 2
; TRIPLETS-NEXT: 16 91 3
; TRIPLETS-NEXT: 0 75 0
; TRIPLETS-NEXT: 0 92 2
; TRIPLETS-NEXT: 16 80 0
; TRIPLETS-NEXT: 16 92 2
; TRIPLETS-NEXT: 16 92 3
; TRIPLETS-NEXT: 16 0 1
; TRIPLETS-NEXT: 0 74 0
; TRIPLETS-NEXT: 0 91 2
; TRIPLETS-NEXT: 30 81 0
; TRIPLETS-NEXT: 30 90 2
; TRIPLETS-NEXT: 0 75 0
; TRIPLETS-NEXT: 0 92 2
; TRIPLETS-NEXT: 30 82 0
; TRIPLETS-NEXT: 30 91 2
; TRIPLETS-NEXT: 30 30 1
; TRIPLETS-NEXT: 30 81 0
; TRIPLETS-NEXT: 30 90 2
; TRIPLETS-NEXT: 30 82 0
; TRIPLETS-NEXT: 30 91 2
; TRIPLETS-NEXT: 30 32 1
; TRIPLETS-NEXT: 32 74 0
; TRIPLETS-NEXT: 32 91 2
; TRIPLETS-NEXT: 32 89 3
; TRIPLETS-NEXT: 32 75 0
; TRIPLETS-NEXT: 32 92 2
; TRIPLETS-NEXT: 32 90 3
; TRIPLETS-NEXT: 32 32 1
; TRIPLETS-NEXT: 32 74 0
; TRIPLETS-NEXT: 32 91 2
; TRIPLETS-NEXT: 32 89 3
; TRIPLETS-NEXT: 32 75 0
; TRIPLETS-NEXT: 32 92 2
; TRIPLETS-NEXT: 32 90 3
; TRIPLETS-NEXT: 32 31 1
; TRIPLETS-NEXT: 31 79 0
; TRIPLETS-NEXT: 31 89 2
; TRIPLETS-NEXT: 31 80 0
; TRIPLETS-NEXT: 31 90 2
; TRIPLETS-NEXT: 31 31 1
; TRIPLETS-NEXT: 31 79 0
; TRIPLETS-NEXT: 31 89 2
; TRIPLETS-NEXT: 31 80 0
; TRIPLETS-NEXT: 31 90 2
; TRIPLETS-NEXT: 31 12 1
; TRIPLETS-NEXT: 12 79 0
; TRIPLETS-NEXT: 12 91 2
; TRIPLETS-NEXT: 12 91 3
; TRIPLETS-NEXT: 12 80 0
; TRIPLETS-NEXT: 12 92 2
; TRIPLETS-NEXT: 12 92 3
; TRIPLETS-NEXT: 12 0 1
; TRIPLETS-NEXT: 0 74 0
; TRIPLETS-NEXT: 0 91 2
; TRIPLETS-NEXT: 0 75 0
; TRIPLETS-NEXT: 0 92 2

View File

@ -320,11 +320,13 @@ TEST_F(IR2VecTestFixture, GetInstVecMap) {
EXPECT_TRUE(InstMap.count(AddInst));
EXPECT_TRUE(InstMap.count(RetInst));
EXPECT_EQ(InstMap.at(AddInst).size(), 2u);
EXPECT_EQ(InstMap.at(RetInst).size(), 2u);
const auto &AddEmb = InstMap.at(AddInst);
const auto &RetEmb = InstMap.at(RetInst);
EXPECT_EQ(AddEmb.size(), 2u);
EXPECT_EQ(RetEmb.size(), 2u);
EXPECT_TRUE(InstMap.at(AddInst).approximatelyEquals(Embedding(2, 27.6)));
EXPECT_TRUE(InstMap.at(RetInst).approximatelyEquals(Embedding(2, 16.8)));
EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 27.9)));
EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 17.0)));
}
TEST_F(IR2VecTestFixture, GetBBVecMap) {
@ -337,9 +339,9 @@ TEST_F(IR2VecTestFixture, GetBBVecMap) {
EXPECT_TRUE(BBMap.count(BB));
EXPECT_EQ(BBMap.at(BB).size(), 2u);
// BB vector should be sum of add and ret: {27.6, 27.6} + {16.8, 16.8} =
// {44.4, 44.4}
EXPECT_TRUE(BBMap.at(BB).approximatelyEquals(Embedding(2, 44.4)));
// BB vector should be sum of add and ret: {27.9, 27.9} + {17.0, 17.0} =
// {44.9, 44.9}
EXPECT_TRUE(BBMap.at(BB).approximatelyEquals(Embedding(2, 44.9)));
}
TEST_F(IR2VecTestFixture, GetBBVector) {
@ -349,7 +351,7 @@ TEST_F(IR2VecTestFixture, GetBBVector) {
const auto &BBVec = Emb->getBBVector(*BB);
EXPECT_EQ(BBVec.size(), 2u);
EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 44.4)));
EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 44.9)));
}
TEST_F(IR2VecTestFixture, GetFunctionVector) {
@ -360,8 +362,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector) {
EXPECT_EQ(FuncVec.size(), 2u);
// Function vector should match BB vector (only one BB): {44.4, 44.4}
EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 44.4)));
// Function vector should match BB vector (only one BB): {44.9, 44.9}
EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 44.9)));
}
static constexpr unsigned MaxOpcodes = Vocabulary::MaxOpcodes;