mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Adding PoisonValue for representing poison value explicitly in IR
Define ConstantData::PoisonValue. Add support for poison value to LLLexer/LLParser/BitcodeReader/BitcodeWriter. Add support for poison value to llvm-c interface. Add support for poison value to OCaml binding. Add m_Poison in PatternMatch. Differential Revision: https://reviews.llvm.org/D71126
This commit is contained in:
parent
10645e58d7
commit
f2658edb7a
@ -314,6 +314,7 @@ module ValueKind = struct
|
|||||||
| GlobalIFunc
|
| GlobalIFunc
|
||||||
| GlobalVariable
|
| GlobalVariable
|
||||||
| UndefValue
|
| UndefValue
|
||||||
|
| PoisonValue
|
||||||
| Instruction of Opcode.t
|
| Instruction of Opcode.t
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -547,8 +548,10 @@ external const_null : lltype -> llvalue = "LLVMConstNull"
|
|||||||
external const_all_ones : (*int|vec*)lltype -> llvalue = "LLVMConstAllOnes"
|
external const_all_ones : (*int|vec*)lltype -> llvalue = "LLVMConstAllOnes"
|
||||||
external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull"
|
external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull"
|
||||||
external undef : lltype -> llvalue = "LLVMGetUndef"
|
external undef : lltype -> llvalue = "LLVMGetUndef"
|
||||||
|
external poison : lltype -> llvalue = "LLVMGetPoison"
|
||||||
external is_null : llvalue -> bool = "llvm_is_null"
|
external is_null : llvalue -> bool = "llvm_is_null"
|
||||||
external is_undef : llvalue -> bool = "llvm_is_undef"
|
external is_undef : llvalue -> bool = "llvm_is_undef"
|
||||||
|
external is_poison : llvalue -> bool = "llvm_is_poison"
|
||||||
external constexpr_opcode : llvalue -> Opcode.t = "llvm_constexpr_get_opcode"
|
external constexpr_opcode : llvalue -> Opcode.t = "llvm_constexpr_get_opcode"
|
||||||
|
|
||||||
(*--... Operations on instructions .........................................--*)
|
(*--... Operations on instructions .........................................--*)
|
||||||
|
@ -347,6 +347,7 @@ module ValueKind : sig
|
|||||||
| GlobalIFunc
|
| GlobalIFunc
|
||||||
| GlobalVariable
|
| GlobalVariable
|
||||||
| UndefValue
|
| UndefValue
|
||||||
|
| PoisonValue
|
||||||
| Instruction of Opcode.t
|
| Instruction of Opcode.t
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -842,6 +843,10 @@ val const_pointer_null : lltype -> llvalue
|
|||||||
See the method [llvm::UndefValue::get]. *)
|
See the method [llvm::UndefValue::get]. *)
|
||||||
val undef : lltype -> llvalue
|
val undef : lltype -> llvalue
|
||||||
|
|
||||||
|
(** [poison ty] returns the poison value of the type [ty].
|
||||||
|
See the method [llvm::PoisonValue::get]. *)
|
||||||
|
val poison : lltype -> llvalue
|
||||||
|
|
||||||
(** [is_null v] returns [true] if the value [v] is the null (zero) value.
|
(** [is_null v] returns [true] if the value [v] is the null (zero) value.
|
||||||
See the method [llvm::Constant::isNullValue]. *)
|
See the method [llvm::Constant::isNullValue]. *)
|
||||||
val is_null : llvalue -> bool
|
val is_null : llvalue -> bool
|
||||||
@ -850,6 +855,10 @@ val is_null : llvalue -> bool
|
|||||||
otherwise. Similar to [llvm::isa<UndefValue>]. *)
|
otherwise. Similar to [llvm::isa<UndefValue>]. *)
|
||||||
val is_undef : llvalue -> bool
|
val is_undef : llvalue -> bool
|
||||||
|
|
||||||
|
(** [is_poison v] returns [true] if the value [v] is a poison value, [false]
|
||||||
|
otherwise. Similar to [llvm::isa<PoisonValue>]. *)
|
||||||
|
val is_poison : llvalue -> bool
|
||||||
|
|
||||||
(** [constexpr_opcode v] returns an [Opcode.t] corresponding to constexpr
|
(** [constexpr_opcode v] returns an [Opcode.t] corresponding to constexpr
|
||||||
value [v], or [Opcode.Invalid] if [v] is not a constexpr. *)
|
value [v], or [Opcode.Invalid] if [v] is not a constexpr. *)
|
||||||
val constexpr_opcode : llvalue -> Opcode.t
|
val constexpr_opcode : llvalue -> Opcode.t
|
||||||
|
@ -627,6 +627,7 @@ enum ValueKind {
|
|||||||
GlobalIFunc,
|
GlobalIFunc,
|
||||||
GlobalVariable,
|
GlobalVariable,
|
||||||
UndefValue,
|
UndefValue,
|
||||||
|
PoisonValue,
|
||||||
Instruction
|
Instruction
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -669,6 +670,7 @@ CAMLprim value llvm_classify_value(LLVMValueRef Val) {
|
|||||||
DEFINE_CASE(Val, MDNode);
|
DEFINE_CASE(Val, MDNode);
|
||||||
DEFINE_CASE(Val, MDString);
|
DEFINE_CASE(Val, MDString);
|
||||||
DEFINE_CASE(Val, UndefValue);
|
DEFINE_CASE(Val, UndefValue);
|
||||||
|
DEFINE_CASE(Val, PoisonValue);
|
||||||
failwith("Unknown Value class");
|
failwith("Unknown Value class");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,6 +764,11 @@ CAMLprim value llvm_is_undef(LLVMValueRef Val) {
|
|||||||
return Val_bool(LLVMIsUndef(Val));
|
return Val_bool(LLVMIsUndef(Val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* llvalue -> bool */
|
||||||
|
CAMLprim value llvm_is_poison(LLVMValueRef Val) {
|
||||||
|
return Val_bool(LLVMIsPoison(Val));
|
||||||
|
}
|
||||||
|
|
||||||
/* llvalue -> Opcode.t */
|
/* llvalue -> Opcode.t */
|
||||||
CAMLprim value llvm_constexpr_get_opcode(LLVMValueRef Val) {
|
CAMLprim value llvm_constexpr_get_opcode(LLVMValueRef Val) {
|
||||||
return LLVMIsAConstantExpr(Val) ?
|
return LLVMIsAConstantExpr(Val) ?
|
||||||
|
@ -269,6 +269,7 @@ typedef enum {
|
|||||||
LLVMConstantVectorValueKind,
|
LLVMConstantVectorValueKind,
|
||||||
|
|
||||||
LLVMUndefValueValueKind,
|
LLVMUndefValueValueKind,
|
||||||
|
LLVMPoisonValueValueKind,
|
||||||
LLVMConstantAggregateZeroValueKind,
|
LLVMConstantAggregateZeroValueKind,
|
||||||
LLVMConstantDataArrayValueKind,
|
LLVMConstantDataArrayValueKind,
|
||||||
LLVMConstantDataVectorValueKind,
|
LLVMConstantDataVectorValueKind,
|
||||||
@ -1562,6 +1563,7 @@ LLVMTypeRef LLVMX86MMXType(void);
|
|||||||
macro(Function) \
|
macro(Function) \
|
||||||
macro(GlobalVariable) \
|
macro(GlobalVariable) \
|
||||||
macro(UndefValue) \
|
macro(UndefValue) \
|
||||||
|
macro(PoisonValue) \
|
||||||
macro(Instruction) \
|
macro(Instruction) \
|
||||||
macro(UnaryOperator) \
|
macro(UnaryOperator) \
|
||||||
macro(BinaryOperator) \
|
macro(BinaryOperator) \
|
||||||
@ -1695,6 +1697,11 @@ LLVMBool LLVMIsConstant(LLVMValueRef Val);
|
|||||||
*/
|
*/
|
||||||
LLVMBool LLVMIsUndef(LLVMValueRef Val);
|
LLVMBool LLVMIsUndef(LLVMValueRef Val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a value instance is poisonous.
|
||||||
|
*/
|
||||||
|
LLVMBool LLVMIsPoison(LLVMValueRef Val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert value instances between types.
|
* Convert value instances between types.
|
||||||
*
|
*
|
||||||
@ -1853,6 +1860,13 @@ LLVMValueRef LLVMConstAllOnes(LLVMTypeRef Ty);
|
|||||||
*/
|
*/
|
||||||
LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty);
|
LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a constant value referring to a poison value of a type.
|
||||||
|
*
|
||||||
|
* @see llvm::PoisonValue::get()
|
||||||
|
*/
|
||||||
|
LLVMValueRef LLVMGetPoison(LLVMTypeRef Ty);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether a value instance is null.
|
* Determine whether a value instance is null.
|
||||||
*
|
*
|
||||||
|
@ -375,6 +375,7 @@ enum ConstantsCodes {
|
|||||||
// asmdialect,asmstr,conststr]
|
// asmdialect,asmstr,conststr]
|
||||||
CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands]
|
CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands]
|
||||||
CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval]
|
CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval]
|
||||||
|
CST_CODE_POISON = 26, // POISON
|
||||||
};
|
};
|
||||||
|
|
||||||
/// CastOpcodes - These are values used in the bitcode files to encode which
|
/// CastOpcodes - These are values used in the bitcode files to encode which
|
||||||
|
@ -1348,13 +1348,16 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant)
|
|||||||
/// can appear to have different bit patterns at each use. See
|
/// can appear to have different bit patterns at each use. See
|
||||||
/// LangRef.html#undefvalues for details.
|
/// LangRef.html#undefvalues for details.
|
||||||
///
|
///
|
||||||
class UndefValue final : public ConstantData {
|
class UndefValue : public ConstantData {
|
||||||
friend class Constant;
|
friend class Constant;
|
||||||
|
|
||||||
explicit UndefValue(Type *T) : ConstantData(T, UndefValueVal) {}
|
explicit UndefValue(Type *T) : ConstantData(T, UndefValueVal) {}
|
||||||
|
|
||||||
void destroyConstantImpl();
|
void destroyConstantImpl();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit UndefValue(Type *T, ValueTy vty) : ConstantData(T, vty) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UndefValue(const UndefValue &) = delete;
|
UndefValue(const UndefValue &) = delete;
|
||||||
|
|
||||||
@ -1381,7 +1384,49 @@ public:
|
|||||||
|
|
||||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
static bool classof(const Value *V) {
|
static bool classof(const Value *V) {
|
||||||
return V->getValueID() == UndefValueVal;
|
return V->getValueID() == UndefValueVal ||
|
||||||
|
V->getValueID() == PoisonValueVal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// In order to facilitate speculative execution, many instructions do not
|
||||||
|
/// invoke immediate undefined behavior when provided with illegal operands,
|
||||||
|
/// and return a poison value instead.
|
||||||
|
///
|
||||||
|
/// see LangRef.html#poisonvalues for details.
|
||||||
|
///
|
||||||
|
class PoisonValue final : public UndefValue {
|
||||||
|
friend class Constant;
|
||||||
|
|
||||||
|
explicit PoisonValue(Type *T) : UndefValue(T, PoisonValueVal) {}
|
||||||
|
|
||||||
|
void destroyConstantImpl();
|
||||||
|
|
||||||
|
public:
|
||||||
|
PoisonValue(const PoisonValue &) = delete;
|
||||||
|
|
||||||
|
/// Static factory methods - Return an 'poison' object of the specified type.
|
||||||
|
static PoisonValue *get(Type *T);
|
||||||
|
|
||||||
|
/// If this poison has array or vector type, return a poison with the right
|
||||||
|
/// element type.
|
||||||
|
PoisonValue *getSequentialElement() const;
|
||||||
|
|
||||||
|
/// If this poison has struct type, return a poison with the right element
|
||||||
|
/// type for the specified element.
|
||||||
|
PoisonValue *getStructElement(unsigned Elt) const;
|
||||||
|
|
||||||
|
/// Return an poison of the right value for the specified GEP index if we can,
|
||||||
|
/// otherwise return null (e.g. if C is a ConstantExpr).
|
||||||
|
PoisonValue *getElementValue(Constant *C) const;
|
||||||
|
|
||||||
|
/// Return an poison of the right value for the specified GEP index.
|
||||||
|
PoisonValue *getElementValue(unsigned Idx) const;
|
||||||
|
|
||||||
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
|
static bool classof(const Value *V) {
|
||||||
|
return V->getValueID() == PoisonValueVal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,6 +96,9 @@ inline class_match<ConstantInt> m_ConstantInt() {
|
|||||||
/// Match an arbitrary undef constant.
|
/// Match an arbitrary undef constant.
|
||||||
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
|
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
|
||||||
|
|
||||||
|
/// Match an arbitrary poison constant.
|
||||||
|
inline class_match<PoisonValue> m_Poison() { return class_match<PoisonValue>(); }
|
||||||
|
|
||||||
/// Match an arbitrary Constant and ignore it.
|
/// Match an arbitrary Constant and ignore it.
|
||||||
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
|
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ HANDLE_CONSTANT(ConstantVector)
|
|||||||
|
|
||||||
// ConstantData.
|
// ConstantData.
|
||||||
HANDLE_CONSTANT(UndefValue)
|
HANDLE_CONSTANT(UndefValue)
|
||||||
|
HANDLE_CONSTANT(PoisonValue)
|
||||||
HANDLE_CONSTANT(ConstantAggregateZero)
|
HANDLE_CONSTANT(ConstantAggregateZero)
|
||||||
HANDLE_CONSTANT(ConstantDataArray)
|
HANDLE_CONSTANT(ConstantDataArray)
|
||||||
HANDLE_CONSTANT(ConstantDataVector)
|
HANDLE_CONSTANT(ConstantDataVector)
|
||||||
|
@ -531,6 +531,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
|||||||
KEYWORD(undef);
|
KEYWORD(undef);
|
||||||
KEYWORD(null);
|
KEYWORD(null);
|
||||||
KEYWORD(none);
|
KEYWORD(none);
|
||||||
|
KEYWORD(poison);
|
||||||
KEYWORD(to);
|
KEYWORD(to);
|
||||||
KEYWORD(caller);
|
KEYWORD(caller);
|
||||||
KEYWORD(within);
|
KEYWORD(within);
|
||||||
|
@ -3273,6 +3273,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) {
|
|||||||
break;
|
break;
|
||||||
case lltok::kw_null: ID.Kind = ValID::t_Null; break;
|
case lltok::kw_null: ID.Kind = ValID::t_Null; break;
|
||||||
case lltok::kw_undef: ID.Kind = ValID::t_Undef; break;
|
case lltok::kw_undef: ID.Kind = ValID::t_Undef; break;
|
||||||
|
case lltok::kw_poison: ID.Kind = ValID::t_Poison; break;
|
||||||
case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break;
|
case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break;
|
||||||
case lltok::kw_none: ID.Kind = ValID::t_None; break;
|
case lltok::kw_none: ID.Kind = ValID::t_None; break;
|
||||||
|
|
||||||
@ -5536,10 +5537,15 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V,
|
|||||||
return error(ID.Loc, "invalid type for none constant");
|
return error(ID.Loc, "invalid type for none constant");
|
||||||
V = Constant::getNullValue(Ty);
|
V = Constant::getNullValue(Ty);
|
||||||
return false;
|
return false;
|
||||||
|
case ValID::t_Poison:
|
||||||
|
// FIXME: LabelTy should not be a first-class type.
|
||||||
|
if (!Ty->isFirstClassType() || Ty->isLabelTy())
|
||||||
|
return error(ID.Loc, "invalid type for poison constant");
|
||||||
|
V = PoisonValue::get(Ty);
|
||||||
|
return false;
|
||||||
case ValID::t_Constant:
|
case ValID::t_Constant:
|
||||||
if (ID.ConstantVal->getType() != Ty)
|
if (ID.ConstantVal->getType() != Ty)
|
||||||
return error(ID.Loc, "constant expression type mismatch");
|
return error(ID.Loc, "constant expression type mismatch");
|
||||||
|
|
||||||
V = ID.ConstantVal;
|
V = ID.ConstantVal;
|
||||||
return false;
|
return false;
|
||||||
case ValID::t_ConstantStruct:
|
case ValID::t_ConstantStruct:
|
||||||
|
@ -46,7 +46,7 @@ namespace llvm {
|
|||||||
t_LocalID, t_GlobalID, // ID in UIntVal.
|
t_LocalID, t_GlobalID, // ID in UIntVal.
|
||||||
t_LocalName, t_GlobalName, // Name in StrVal.
|
t_LocalName, t_GlobalName, // Name in StrVal.
|
||||||
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
|
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
|
||||||
t_Null, t_Undef, t_Zero, t_None, // No value.
|
t_Null, t_Undef, t_Zero, t_None, t_Poison, // No value.
|
||||||
t_EmptyArray, // No value: []
|
t_EmptyArray, // No value: []
|
||||||
t_Constant, // Value in ConstantVal.
|
t_Constant, // Value in ConstantVal.
|
||||||
t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal.
|
t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal.
|
||||||
|
@ -74,6 +74,7 @@ enum Kind {
|
|||||||
kw_localexec,
|
kw_localexec,
|
||||||
kw_zeroinitializer,
|
kw_zeroinitializer,
|
||||||
kw_undef,
|
kw_undef,
|
||||||
|
kw_poison,
|
||||||
kw_null,
|
kw_null,
|
||||||
kw_none,
|
kw_none,
|
||||||
kw_to,
|
kw_to,
|
||||||
|
@ -2410,6 +2410,9 @@ Error BitcodeReader::parseConstants() {
|
|||||||
case bitc::CST_CODE_UNDEF: // UNDEF
|
case bitc::CST_CODE_UNDEF: // UNDEF
|
||||||
V = UndefValue::get(CurTy);
|
V = UndefValue::get(CurTy);
|
||||||
break;
|
break;
|
||||||
|
case bitc::CST_CODE_POISON: // POISON
|
||||||
|
V = PoisonValue::get(CurTy);
|
||||||
|
break;
|
||||||
case bitc::CST_CODE_SETTYPE: // SETTYPE: [typeid]
|
case bitc::CST_CODE_SETTYPE: // SETTYPE: [typeid]
|
||||||
if (Record.empty())
|
if (Record.empty())
|
||||||
return error("Invalid record");
|
return error("Invalid record");
|
||||||
|
@ -2425,6 +2425,8 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
|
|||||||
unsigned AbbrevToUse = 0;
|
unsigned AbbrevToUse = 0;
|
||||||
if (C->isNullValue()) {
|
if (C->isNullValue()) {
|
||||||
Code = bitc::CST_CODE_NULL;
|
Code = bitc::CST_CODE_NULL;
|
||||||
|
} else if (isa<PoisonValue>(C)) {
|
||||||
|
Code = bitc::CST_CODE_POISON;
|
||||||
} else if (isa<UndefValue>(C)) {
|
} else if (isa<UndefValue>(C)) {
|
||||||
Code = bitc::CST_CODE_UNDEF;
|
Code = bitc::CST_CODE_UNDEF;
|
||||||
} else if (const ConstantInt *IV = dyn_cast<ConstantInt>(C)) {
|
} else if (const ConstantInt *IV = dyn_cast<ConstantInt>(C)) {
|
||||||
|
@ -1568,6 +1568,11 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isa<PoisonValue>(CV)) {
|
||||||
|
Out << "poison";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isa<UndefValue>(CV)) {
|
if (isa<UndefValue>(CV)) {
|
||||||
Out << "undef";
|
Out << "undef";
|
||||||
return;
|
return;
|
||||||
|
@ -1089,6 +1089,32 @@ unsigned UndefValue::getNumElements() const {
|
|||||||
return Ty->getStructNumElements();
|
return Ty->getStructNumElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// PoisonValue Implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
PoisonValue *PoisonValue::getSequentialElement() const {
|
||||||
|
if (ArrayType *ATy = dyn_cast<ArrayType>(getType()))
|
||||||
|
return PoisonValue::get(ATy->getElementType());
|
||||||
|
return PoisonValue::get(cast<VectorType>(getType())->getElementType());
|
||||||
|
}
|
||||||
|
|
||||||
|
PoisonValue *PoisonValue::getStructElement(unsigned Elt) const {
|
||||||
|
return PoisonValue::get(getType()->getStructElementType(Elt));
|
||||||
|
}
|
||||||
|
|
||||||
|
PoisonValue *PoisonValue::getElementValue(Constant *C) const {
|
||||||
|
if (isa<ArrayType>(getType()) || isa<VectorType>(getType()))
|
||||||
|
return getSequentialElement();
|
||||||
|
return getStructElement(cast<ConstantInt>(C)->getZExtValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
PoisonValue *PoisonValue::getElementValue(unsigned Idx) const {
|
||||||
|
if (isa<ArrayType>(getType()) || isa<VectorType>(getType()))
|
||||||
|
return getSequentialElement();
|
||||||
|
return getStructElement(Idx);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ConstantXXX Classes
|
// ConstantXXX Classes
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -1699,6 +1725,20 @@ void UndefValue::destroyConstantImpl() {
|
|||||||
getContext().pImpl->UVConstants.erase(getType());
|
getContext().pImpl->UVConstants.erase(getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PoisonValue *PoisonValue::get(Type *Ty) {
|
||||||
|
std::unique_ptr<PoisonValue> &Entry = Ty->getContext().pImpl->PVConstants[Ty];
|
||||||
|
if (!Entry)
|
||||||
|
Entry.reset(new PoisonValue(Ty));
|
||||||
|
|
||||||
|
return Entry.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove the constant from the constant table.
|
||||||
|
void PoisonValue::destroyConstantImpl() {
|
||||||
|
// Free the constant and any dangling references to it.
|
||||||
|
getContext().pImpl->PVConstants.erase(getType());
|
||||||
|
}
|
||||||
|
|
||||||
BlockAddress *BlockAddress::get(BasicBlock *BB) {
|
BlockAddress *BlockAddress::get(BasicBlock *BB) {
|
||||||
assert(BB->getParent() && "Block must have a parent");
|
assert(BB->getParent() && "Block must have a parent");
|
||||||
return get(BB->getParent(), BB);
|
return get(BB->getParent(), BB);
|
||||||
|
@ -1046,6 +1046,10 @@ LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty) {
|
|||||||
return wrap(UndefValue::get(unwrap(Ty)));
|
return wrap(UndefValue::get(unwrap(Ty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMValueRef LLVMGetPoison(LLVMTypeRef Ty) {
|
||||||
|
return wrap(PoisonValue::get(unwrap(Ty)));
|
||||||
|
}
|
||||||
|
|
||||||
LLVMBool LLVMIsConstant(LLVMValueRef Ty) {
|
LLVMBool LLVMIsConstant(LLVMValueRef Ty) {
|
||||||
return isa<Constant>(unwrap(Ty));
|
return isa<Constant>(unwrap(Ty));
|
||||||
}
|
}
|
||||||
@ -1060,6 +1064,10 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val) {
|
|||||||
return isa<UndefValue>(unwrap(Val));
|
return isa<UndefValue>(unwrap(Val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMBool LLVMIsPoison(LLVMValueRef Val) {
|
||||||
|
return isa<PoisonValue>(unwrap(Val));
|
||||||
|
}
|
||||||
|
|
||||||
LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty) {
|
LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty) {
|
||||||
return wrap(ConstantPointerNull::get(unwrap<PointerType>(Ty)));
|
return wrap(ConstantPointerNull::get(unwrap<PointerType>(Ty)));
|
||||||
}
|
}
|
||||||
|
@ -1376,6 +1376,8 @@ public:
|
|||||||
|
|
||||||
DenseMap<Type *, std::unique_ptr<UndefValue>> UVConstants;
|
DenseMap<Type *, std::unique_ptr<UndefValue>> UVConstants;
|
||||||
|
|
||||||
|
DenseMap<Type *, std::unique_ptr<PoisonValue>> PVConstants;
|
||||||
|
|
||||||
StringMap<std::unique_ptr<ConstantDataSequential>> CDSConstants;
|
StringMap<std::unique_ptr<ConstantDataSequential>> CDSConstants;
|
||||||
|
|
||||||
DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
|
DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
|
||||||
|
@ -262,6 +262,14 @@ let test_constants () =
|
|||||||
insist (i1_type = type_of c);
|
insist (i1_type = type_of c);
|
||||||
insist (is_undef c);
|
insist (is_undef c);
|
||||||
|
|
||||||
|
(* CHECK: const_poison{{.*}}poison
|
||||||
|
*)
|
||||||
|
group "poison";
|
||||||
|
let c = poison i1_type in
|
||||||
|
ignore (define_global "const_poison" c m);
|
||||||
|
insist (i1_type = type_of c);
|
||||||
|
insist (is_poison c);
|
||||||
|
|
||||||
group "constant arithmetic";
|
group "constant arithmetic";
|
||||||
(* CHECK: @const_neg = global i64 sub
|
(* CHECK: @const_neg = global i64 sub
|
||||||
* CHECK: @const_nsw_neg = global i64 sub nsw
|
* CHECK: @const_nsw_neg = global i64 sub nsw
|
||||||
|
@ -41,10 +41,10 @@ $comdat.samesize = comdat samesize
|
|||||||
; CHECK: @const.float = constant double 0.0
|
; CHECK: @const.float = constant double 0.0
|
||||||
@const.null = constant i8* null
|
@const.null = constant i8* null
|
||||||
; CHECK: @const.null = constant i8* null
|
; CHECK: @const.null = constant i8* null
|
||||||
%const.struct.type = type { i32, i8 }
|
%const.struct.type = type { i32, i8, i64 }
|
||||||
%const.struct.type.packed = type <{ i32, i8 }>
|
%const.struct.type.packed = type <{ i32, i8 }>
|
||||||
@const.struct = constant %const.struct.type { i32 -1, i8 undef }
|
@const.struct = constant %const.struct.type { i32 -1, i8 undef, i64 poison }
|
||||||
; CHECK: @const.struct = constant %const.struct.type { i32 -1, i8 undef }
|
; CHECK: @const.struct = constant %const.struct.type { i32 -1, i8 undef, i64 poison }
|
||||||
@const.struct.packed = constant %const.struct.type.packed <{ i32 -1, i8 1 }>
|
@const.struct.packed = constant %const.struct.type.packed <{ i32 -1, i8 1 }>
|
||||||
; CHECK: @const.struct.packed = constant %const.struct.type.packed <{ i32 -1, i8 1 }>
|
; CHECK: @const.struct.packed = constant %const.struct.type.packed <{ i32 -1, i8 1 }>
|
||||||
|
|
||||||
@ -1075,6 +1075,8 @@ exc:
|
|||||||
|
|
||||||
resume i32 undef
|
resume i32 undef
|
||||||
; CHECK: resume i32 undef
|
; CHECK: resume i32 undef
|
||||||
|
resume i32 poison
|
||||||
|
; CHECK: resume i32 poison
|
||||||
unreachable
|
unreachable
|
||||||
; CHECK: unreachable
|
; CHECK: unreachable
|
||||||
|
|
||||||
@ -1354,6 +1356,14 @@ define void @instructions.conversions() {
|
|||||||
; CHECK: fptoui float undef to i32
|
; CHECK: fptoui float undef to i32
|
||||||
fptosi float undef to i32
|
fptosi float undef to i32
|
||||||
; CHECK: fptosi float undef to i32
|
; CHECK: fptosi float undef to i32
|
||||||
|
fptrunc float poison to half
|
||||||
|
; CHECK: fptrunc float poison to half
|
||||||
|
fpext half poison to float
|
||||||
|
; CHECK: fpext half poison to float
|
||||||
|
fptoui float poison to i32
|
||||||
|
; CHECK: fptoui float poison to i32
|
||||||
|
fptosi float poison to i32
|
||||||
|
; CHECK: fptosi float poison to i32
|
||||||
uitofp i32 1 to float
|
uitofp i32 1 to float
|
||||||
; CHECK: uitofp i32 1 to float
|
; CHECK: uitofp i32 1 to float
|
||||||
sitofp i32 -1 to float
|
sitofp i32 -1 to float
|
||||||
|
458
test/CodeGen/X86/poison-ops.ll
Normal file
458
test/CodeGen/X86/poison-ops.ll
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
; NOTE: This test case is borrowed from undef-ops.ll
|
||||||
|
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @add_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: add_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = add i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @add_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: add_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = add <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @add_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: add_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = add i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @add_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: add_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = add <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sub_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: sub_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sub i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @sub_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: sub_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sub <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sub_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: sub_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sub i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @sub_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: sub_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sub <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @mul_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: mul_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = mul i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @mul_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: mul_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = mul <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @mul_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: mul_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = mul i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @mul_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: mul_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = mul <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sdiv_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: sdiv_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sdiv i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @sdiv_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: sdiv_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sdiv <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sdiv_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: sdiv_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sdiv i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @sdiv_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: sdiv_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = sdiv <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @udiv_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: udiv_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = udiv i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @udiv_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: udiv_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = udiv <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @udiv_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: udiv_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = udiv i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @udiv_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: udiv_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = udiv <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @srem_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: srem_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = srem i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @srem_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: srem_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = srem <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @srem_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: srem_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = srem i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @srem_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: srem_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = srem <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @urem_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: urem_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = urem i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @urem_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: urem_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = urem <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @urem_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: urem_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = urem i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @urem_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: urem_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = urem <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @ashr_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: ashr_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = ashr i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @ashr_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: ashr_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = ashr <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @ashr_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: ashr_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = ashr i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @ashr_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: ashr_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = ashr <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @lshr_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: lshr_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = lshr i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @lshr_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: lshr_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = lshr <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @lshr_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: lshr_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = lshr i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @lshr_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: lshr_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = lshr <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @shl_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: shl_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = shl i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @shl_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: shl_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = shl <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @shl_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: shl_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = shl i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @shl_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: shl_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = shl <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @and_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: and_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = and i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @and_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: and_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = and <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @and_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: and_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = and i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @and_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: and_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: xorps %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = and <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @or_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: or_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: movl $-1, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = or i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @or_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: or_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: pcmpeqd %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = or <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @or_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: or_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: movl $-1, %eax
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = or i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @or_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: or_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: pcmpeqd %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = or <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @xor_poison_rhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: xor_poison_rhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = xor i32 %x, poison
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @xor_poison_rhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: xor_poison_rhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = xor <4 x i32> %x, poison
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @xor_poison_lhs(i32 %x) {
|
||||||
|
; CHECK-LABEL: xor_poison_lhs:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = xor i32 poison, %x
|
||||||
|
ret i32 %r
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i32> @xor_poison_lhs_vec(<4 x i32> %x) {
|
||||||
|
; CHECK-LABEL: xor_poison_lhs_vec:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%r = xor <4 x i32> poison, %x
|
||||||
|
ret <4 x i32> %r
|
||||||
|
}
|
||||||
|
|
||||||
|
; This would crash because the shift amount is an i8 operand,
|
||||||
|
; but the result of the shift is i32. We can't just propagate
|
||||||
|
; the existing poison as the result.
|
||||||
|
|
||||||
|
define i1 @poison_operand_size_not_same_as_result() {
|
||||||
|
; CHECK-LABEL: poison_operand_size_not_same_as_result:
|
||||||
|
; CHECK: # %bb.0:
|
||||||
|
; CHECK-NEXT: retq
|
||||||
|
%sh = shl i32 7, poison
|
||||||
|
%cmp = icmp eq i32 0, %sh
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
@ -344,6 +344,12 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
|
|||||||
return LLVMGetUndef(TypeCloner(M).Clone(Cst));
|
return LLVMGetUndef(TypeCloner(M).Clone(Cst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try poison
|
||||||
|
if (LLVMIsPoison(Cst)) {
|
||||||
|
check_value_kind(Cst, LLVMPoisonValueValueKind);
|
||||||
|
return LLVMGetPoison(TypeCloner(M).Clone(Cst));
|
||||||
|
}
|
||||||
|
|
||||||
// Try null
|
// Try null
|
||||||
if (LLVMIsNull(Cst)) {
|
if (LLVMIsNull(Cst)) {
|
||||||
check_value_kind(Cst, LLVMConstantTokenNoneValueKind);
|
check_value_kind(Cst, LLVMConstantTokenNoneValueKind);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user