mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-15 22:32:35 +00:00
Extend the vcmp/fcmp LLVM IR instructions to take vectors as arguments
and, if so, to return a vector of boolean as a result; Extend the select LLVM IR instruction to allow you to specify a result type which is a vector of boolean, in which case the result will be an element-wise selection instead of choosing one vector or the other; and Update LangRef.html to describe these changes. This patch was contributed by Preston Gurd! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55969 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3eb594013f
commit
f72fb679ef
@ -3846,11 +3846,12 @@ instructions, which defy better classification.</p>
|
||||
</div>
|
||||
<div class="doc_text">
|
||||
<h5>Syntax:</h5>
|
||||
<pre> <result> = icmp <cond> <ty> <op1>, <op2> <i>; yields {i1}:result</i>
|
||||
<pre> <result> = icmp <cond> <ty> <op1>, <op2> <i>; yields {i1} or {<N x i1>}:result</i>
|
||||
</pre>
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>icmp</tt>' instruction returns a boolean value based on comparison
|
||||
of its two integer or pointer operands.</p>
|
||||
<p>The '<tt>icmp</tt>' instruction returns a boolean value or
|
||||
a vector of boolean values based on comparison
|
||||
of its two integer, integer vector, or pointer operands.</p>
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>icmp</tt>' instruction takes three operands. The first operand is
|
||||
the condition code indicating the kind of comparison to perform. It is not
|
||||
@ -3868,11 +3869,13 @@ a value, just a keyword. The possible condition code are:
|
||||
<li><tt>sle</tt>: signed less or equal</li>
|
||||
</ol>
|
||||
<p>The remaining two arguments must be <a href="#t_integer">integer</a> or
|
||||
<a href="#t_pointer">pointer</a> typed. They must also be identical types.</p>
|
||||
<a href="#t_pointer">pointer</a>
|
||||
or integer <a href="#t_vector">vector</a> typed.
|
||||
They must also be identical types.</p>
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>icmp</tt>' compares <tt>op1</tt> and <tt>op2</tt> according to
|
||||
the condition code given as <tt>cond</tt>. The comparison performed always
|
||||
yields a <a href="#t_primitive">i1</a> result, as follows:
|
||||
yields either an <a href="#t_primitive"><tt>i1</tt></a> or vector of <tt>i1</tt> result, as follows:
|
||||
<ol>
|
||||
<li><tt>eq</tt>: yields <tt>true</tt> if the operands are equal,
|
||||
<tt>false</tt> otherwise. No sign interpretation is necessary or performed.
|
||||
@ -3898,6 +3901,11 @@ yields a <a href="#t_primitive">i1</a> result, as follows:
|
||||
</ol>
|
||||
<p>If the operands are <a href="#t_pointer">pointer</a> typed, the pointer
|
||||
values are compared as if they were integers.</p>
|
||||
<p>If the operands are integer vectors, then they are compared
|
||||
element by element. The result is an <tt>i1</tt> vector with
|
||||
the same number of elements as the values being compared.
|
||||
Otherwise, the result is an <tt>i1</tt>.
|
||||
</p>
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre> <result> = icmp eq i32 4, 5 <i>; yields: result=false</i>
|
||||
@ -3914,11 +3922,19 @@ values are compared as if they were integers.</p>
|
||||
</div>
|
||||
<div class="doc_text">
|
||||
<h5>Syntax:</h5>
|
||||
<pre> <result> = fcmp <cond> <ty> <op1>, <op2> <i>; yields {i1}:result</i>
|
||||
<pre> <result> = fcmp <cond> <ty> <op1>, <op2> <i>; yields {i1} or {<N x i1>}:result</i>
|
||||
</pre>
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>fcmp</tt>' instruction returns a boolean value based on comparison
|
||||
of its floating point operands.</p>
|
||||
<p>The '<tt>fcmp</tt>' instruction returns a boolean value
|
||||
or vector of boolean values based on comparison
|
||||
of its operands.
|
||||
<p>
|
||||
If the operands are floating point scalars, then the result
|
||||
type is a boolean (<a href="#t_primitive"><tt>i1</tt></a>).
|
||||
</p>
|
||||
<p>If the operands are floating point vectors, then the result type
|
||||
is a vector of boolean with the same number of elements as the
|
||||
operands being compared.</p>
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>fcmp</tt>' instruction takes three operands. The first operand is
|
||||
the condition code indicating the kind of comparison to perform. It is not
|
||||
@ -3943,13 +3959,17 @@ a value, just a keyword. The possible condition code are:
|
||||
</ol>
|
||||
<p><i>Ordered</i> means that neither operand is a QNAN while
|
||||
<i>unordered</i> means that either operand may be a QNAN.</p>
|
||||
<p>The <tt>val1</tt> and <tt>val2</tt> arguments must be
|
||||
<a href="#t_floating">floating point</a> typed. They must have identical
|
||||
types.</p>
|
||||
<p>Each of <tt>val1</tt> and <tt>val2</tt> arguments must be
|
||||
either a <a href="#t_floating">floating point</a> type
|
||||
or a <a href="#t_vector">vector</a> of floating point type.
|
||||
They must have identical types.</p>
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>fcmp</tt>' instruction compares <tt>op1</tt> and <tt>op2</tt>
|
||||
according to the condition code given as <tt>cond</tt>. The comparison performed
|
||||
always yields a <a href="#t_primitive">i1</a> result, as follows:
|
||||
according to the condition code given as <tt>cond</tt>.
|
||||
If the operands are vectors, then the vectors are compared
|
||||
element by element.
|
||||
Each comparison performed
|
||||
always yields an <a href="#t_primitive">i1</a> result, as follows:
|
||||
<ol>
|
||||
<li><tt>false</tt>: always yields <tt>false</tt>, regardless of operands.</li>
|
||||
<li><tt>oeq</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
@ -3983,9 +4003,9 @@ always yields a <a href="#t_primitive">i1</a> result, as follows:
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre> <result> = fcmp oeq float 4.0, 5.0 <i>; yields: result=false</i>
|
||||
<result> = icmp one float 4.0, 5.0 <i>; yields: result=true</i>
|
||||
<result> = icmp olt float 4.0, 5.0 <i>; yields: result=true</i>
|
||||
<result> = icmp ueq double 1.0, 2.0 <i>; yields: result=false</i>
|
||||
<result> = fcmp one float 4.0, 5.0 <i>; yields: result=true</i>
|
||||
<result> = fcmp olt float 4.0, 5.0 <i>; yields: result=true</i>
|
||||
<result> = fcmp ueq double 1.0, 2.0 <i>; yields: result=false</i>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -4016,7 +4036,7 @@ a value, just a keyword. The possible condition code are:
|
||||
<li><tt>slt</tt>: signed less than</li>
|
||||
<li><tt>sle</tt>: signed less or equal</li>
|
||||
</ol>
|
||||
<p>The remaining two arguments must be <a href="#t_vector">vector</a> of
|
||||
<p>The remaining two arguments must be <a href="#t_vector">vector</a> or
|
||||
<a href="#t_integer">integer</a> typed. They must also be identical types.</p>
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>vicmp</tt>' instruction compares <tt>op1</tt> and <tt>op2</tt>
|
||||
@ -4140,7 +4160,9 @@ Loop: ; Infinite loop that counts from 0 on up...
|
||||
<h5>Syntax:</h5>
|
||||
|
||||
<pre>
|
||||
<result> = select i1 <cond>, <ty> <val1>, <ty> <val2> <i>; yields ty</i>
|
||||
<result> = select <i>selty</i> <cond>, <ty> <val1>, <ty> <val2> <i>; yields ty</i>
|
||||
|
||||
<i>selty</i> is either i1 or {<N x i1>}
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
@ -4154,18 +4176,25 @@ condition, without branching.
|
||||
<h5>Arguments:</h5>
|
||||
|
||||
<p>
|
||||
The '<tt>select</tt>' instruction requires an 'i1' value indicating the
|
||||
The '<tt>select</tt>' instruction requires an 'i1' value or
|
||||
a vector of 'i1' values indicating the
|
||||
condition, and two values of the same <a href="#t_firstclass">first class</a>
|
||||
type. If the val1/val2 are vectors, the entire vectors are selected, not
|
||||
type. If the val1/val2 are vectors and
|
||||
the condition is a scalar, then entire vectors are selected, not
|
||||
individual elements.
|
||||
</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>
|
||||
If the i1 condition evaluates is 1, the instruction returns the first
|
||||
If the condition is an i1 and it evaluates to 1, the instruction returns the first
|
||||
value argument; otherwise, it returns the second value argument.
|
||||
</p>
|
||||
<p>
|
||||
If the condition is a vector of i1, then the value arguments must
|
||||
be vectors of the same size, and the selection is done element
|
||||
by element.
|
||||
</p>
|
||||
|
||||
<h5>Example:</h5>
|
||||
|
||||
|
@ -205,7 +205,9 @@ namespace bitc {
|
||||
// FIXME: Remove GETRESULT in favor of EXTRACTVAL in LLVM 3.0
|
||||
FUNC_CODE_INST_GETRESULT = 25, // GETRESULT: [ty, opval, n]
|
||||
FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands]
|
||||
FUNC_CODE_INST_INSERTVAL = 27 // INSERTVAL: [n x operands]
|
||||
FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands]
|
||||
// fcmp/icmp returning vector of Int1Ty, NOT for vicmp/vfcmp
|
||||
FUNC_CODE_INST_VCMP = 28 // VCMP: [opty, opval, opval, pred]
|
||||
};
|
||||
} // End bitc namespace
|
||||
} // End llvm namespace
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/OperandTraits.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -732,6 +733,13 @@ public:
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
/// @brief Create a result type for fcmp/icmp (but not vicmp/vfcmp)
|
||||
static const Type* makeCmpResultType(const Type* opnd_type) {
|
||||
if (const VectorType* vt = dyn_cast<const VectorType>(opnd_type)) {
|
||||
return VectorType::get(Type::Int1Ty, vt->getNumElements());
|
||||
}
|
||||
return Type::Int1Ty;
|
||||
}
|
||||
/// Backward-compatible interfaces
|
||||
/// @deprecated in 2.4, do not use, will disappear soon
|
||||
static CmpInst *create(OtherOps Op, unsigned short predicate, Value *S1,
|
||||
|
@ -621,7 +621,8 @@ public:
|
||||
Value *RHS, ///< The right-hand-side of the expression
|
||||
const std::string &NameStr = "", ///< Name of the instruction
|
||||
Instruction *InsertBefore = 0 ///< Where to insert
|
||||
) : CmpInst(Type::Int1Ty, Instruction::ICmp, pred, LHS, RHS, NameStr,
|
||||
) : CmpInst(makeCmpResultType(LHS->getType()),
|
||||
Instruction::ICmp, pred, LHS, RHS, NameStr,
|
||||
InsertBefore) {
|
||||
assert(pred >= CmpInst::FIRST_ICMP_PREDICATE &&
|
||||
pred <= CmpInst::LAST_ICMP_PREDICATE &&
|
||||
@ -629,7 +630,7 @@ public:
|
||||
assert(getOperand(0)->getType() == getOperand(1)->getType() &&
|
||||
"Both operands to ICmp instruction are not of the same type!");
|
||||
// Check that the operands are the right type
|
||||
assert((getOperand(0)->getType()->isInteger() ||
|
||||
assert((getOperand(0)->getType()->isIntOrIntVector() ||
|
||||
isa<PointerType>(getOperand(0)->getType())) &&
|
||||
"Invalid operand types for ICmp instruction");
|
||||
}
|
||||
@ -641,7 +642,8 @@ public:
|
||||
Value *RHS, ///< The right-hand-side of the expression
|
||||
const std::string &NameStr, ///< Name of the instruction
|
||||
BasicBlock *InsertAtEnd ///< Block to insert into.
|
||||
) : CmpInst(Type::Int1Ty, Instruction::ICmp, pred, LHS, RHS, NameStr,
|
||||
) : CmpInst(makeCmpResultType(LHS->getType()),
|
||||
Instruction::ICmp, pred, LHS, RHS, NameStr,
|
||||
InsertAtEnd) {
|
||||
assert(pred >= CmpInst::FIRST_ICMP_PREDICATE &&
|
||||
pred <= CmpInst::LAST_ICMP_PREDICATE &&
|
||||
@ -649,7 +651,7 @@ public:
|
||||
assert(getOperand(0)->getType() == getOperand(1)->getType() &&
|
||||
"Both operands to ICmp instruction are not of the same type!");
|
||||
// Check that the operands are the right type
|
||||
assert((getOperand(0)->getType()->isInteger() ||
|
||||
assert((getOperand(0)->getType()->isIntOrIntVector() ||
|
||||
isa<PointerType>(getOperand(0)->getType())) &&
|
||||
"Invalid operand types for ICmp instruction");
|
||||
}
|
||||
@ -754,6 +756,7 @@ public:
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -773,14 +776,15 @@ public:
|
||||
Value *RHS, ///< The right-hand-side of the expression
|
||||
const std::string &NameStr = "", ///< Name of the instruction
|
||||
Instruction *InsertBefore = 0 ///< Where to insert
|
||||
) : CmpInst(Type::Int1Ty, Instruction::FCmp, pred, LHS, RHS, NameStr,
|
||||
) : CmpInst(makeCmpResultType(LHS->getType()),
|
||||
Instruction::FCmp, pred, LHS, RHS, NameStr,
|
||||
InsertBefore) {
|
||||
assert(pred <= FCmpInst::LAST_FCMP_PREDICATE &&
|
||||
"Invalid FCmp predicate value");
|
||||
assert(getOperand(0)->getType() == getOperand(1)->getType() &&
|
||||
"Both operands to FCmp instruction are not of the same type!");
|
||||
// Check that the operands are the right type
|
||||
assert(getOperand(0)->getType()->isFloatingPoint() &&
|
||||
assert(getOperand(0)->getType()->isFPOrFPVector() &&
|
||||
"Invalid operand types for FCmp instruction");
|
||||
}
|
||||
|
||||
@ -791,14 +795,15 @@ public:
|
||||
Value *RHS, ///< The right-hand-side of the expression
|
||||
const std::string &NameStr, ///< Name of the instruction
|
||||
BasicBlock *InsertAtEnd ///< Block to insert into.
|
||||
) : CmpInst(Type::Int1Ty, Instruction::FCmp, pred, LHS, RHS, NameStr,
|
||||
) : CmpInst(makeCmpResultType(LHS->getType()),
|
||||
Instruction::FCmp, pred, LHS, RHS, NameStr,
|
||||
InsertAtEnd) {
|
||||
assert(pred <= FCmpInst::LAST_FCMP_PREDICATE &&
|
||||
"Invalid FCmp predicate value");
|
||||
assert(getOperand(0)->getType() == getOperand(1)->getType() &&
|
||||
"Both operands to FCmp instruction are not of the same type!");
|
||||
// Check that the operands are the right type
|
||||
assert(getOperand(0)->getType()->isFloatingPoint() &&
|
||||
assert(getOperand(0)->getType()->isFPOrFPVector() &&
|
||||
"Invalid operand types for FCmp instruction");
|
||||
}
|
||||
|
||||
@ -837,6 +842,7 @@ public:
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1102,7 +1102,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
|
||||
%token <BinaryOpVal> ADD SUB MUL UDIV SDIV FDIV UREM SREM FREM AND OR XOR
|
||||
%token <BinaryOpVal> SHL LSHR ASHR
|
||||
|
||||
%token <OtherOpVal> ICMP FCMP VICMP VFCMP
|
||||
%token <OtherOpVal> ICMP FCMP VICMP VFCMP
|
||||
%type <IPredicate> IPredicates
|
||||
%type <FPredicate> FPredicates
|
||||
%token EQ NE SLT SGT SLE SGE ULT UGT ULE UGE
|
||||
@ -3097,8 +3097,6 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
| ICMP IPredicates Types ValueRef ',' ValueRef {
|
||||
if (!UpRefs.empty())
|
||||
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
|
||||
if (isa<VectorType>((*$3).get()))
|
||||
GEN_ERROR("Vector types not supported by icmp instruction");
|
||||
Value* tmpVal1 = getVal(*$3, $4);
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$3, $6);
|
||||
@ -3111,8 +3109,6 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
| FCMP FPredicates Types ValueRef ',' ValueRef {
|
||||
if (!UpRefs.empty())
|
||||
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
|
||||
if (isa<VectorType>((*$3).get()))
|
||||
GEN_ERROR("Vector types not supported by fcmp instruction");
|
||||
Value* tmpVal1 = getVal(*$3, $4);
|
||||
CHECK_FOR_ERROR
|
||||
Value* tmpVal2 = getVal(*$3, $6);
|
||||
@ -3133,7 +3129,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
CHECK_FOR_ERROR
|
||||
$$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("icmp operator returned null");
|
||||
GEN_ERROR("vicmp operator returned null");
|
||||
delete $3;
|
||||
}
|
||||
| VFCMP FPredicates Types ValueRef ',' ValueRef {
|
||||
@ -3147,7 +3143,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
CHECK_FOR_ERROR
|
||||
$$ = CmpInst::Create($1, $2, tmpVal1, tmpVal2);
|
||||
if ($$ == 0)
|
||||
GEN_ERROR("fcmp operator returned null");
|
||||
GEN_ERROR("vfcmp operator returned null");
|
||||
delete $3;
|
||||
}
|
||||
| CastOps ResolvedVal TO Types {
|
||||
@ -3163,10 +3159,23 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||
delete $4;
|
||||
}
|
||||
| SELECT ResolvedVal ',' ResolvedVal ',' ResolvedVal {
|
||||
if ($2->getType() != Type::Int1Ty)
|
||||
GEN_ERROR("select condition must be boolean");
|
||||
if (isa<VectorType>($2->getType())) {
|
||||
// vector select
|
||||
if (!isa<VectorType>($4->getType())
|
||||
|| !isa<VectorType>($6->getType()) )
|
||||
GEN_ERROR("vector select value types must be vector types");
|
||||
const VectorType* cond_type = cast<VectorType>($2->getType());
|
||||
const VectorType* select_type = cast<VectorType>($4->getType());
|
||||
if (cond_type->getElementType() != Type::Int1Ty)
|
||||
GEN_ERROR("vector select condition element type must be boolean");
|
||||
if (cond_type->getNumElements() != select_type->getNumElements())
|
||||
GEN_ERROR("vector select number of elements must be the same");
|
||||
} else {
|
||||
if ($2->getType() != Type::Int1Ty)
|
||||
GEN_ERROR("select condition must be boolean");
|
||||
}
|
||||
if ($4->getType() != $6->getType())
|
||||
GEN_ERROR("select value types should match");
|
||||
GEN_ERROR("select value types must match");
|
||||
$$ = SelectInst::Create($2, $4, $6);
|
||||
CHECK_FOR_ERROR
|
||||
}
|
||||
|
@ -1499,8 +1499,19 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
||||
Value *TrueVal, *FalseVal, *Cond;
|
||||
if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
|
||||
getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
|
||||
getValue(Record, OpNum, Type::Int1Ty, Cond))
|
||||
getValue(Record, OpNum, 0 /*skip type check*/, Cond))
|
||||
return Error("Invalid SELECT record");
|
||||
|
||||
// select condition can be either i1 or [N x i1]
|
||||
if (const VectorType* vector_type = dyn_cast<const VectorType>(Cond->getType())) {
|
||||
// expect <n x i1>
|
||||
if (vector_type->getElementType() != Type::Int1Ty)
|
||||
return Error("Invalid SELECT condition type");
|
||||
} else {
|
||||
// expect i1
|
||||
if (Cond->getType() != Type::Int1Ty)
|
||||
return Error("Invalid SELECT condition type");
|
||||
}
|
||||
|
||||
I = SelectInst::Create(Cond, TrueVal, FalseVal);
|
||||
break;
|
||||
@ -1563,6 +1574,22 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
||||
I = new VICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_VCMP: { // VCMP: [opty, opval, opval, pred]
|
||||
// Fcmp/ICmp returning vector of bool
|
||||
unsigned OpNum = 0;
|
||||
Value *LHS, *RHS;
|
||||
if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
|
||||
getValue(Record, OpNum, LHS->getType(), RHS) ||
|
||||
OpNum+1 != Record.size())
|
||||
return Error("Invalid VCMP record");
|
||||
|
||||
// will always be vector
|
||||
if (LHS->getType()->isFPOrFPVector())
|
||||
I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS);
|
||||
else
|
||||
I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS);
|
||||
break;
|
||||
}
|
||||
case bitc::FUNC_CODE_INST_GETRESULT: { // GETRESULT: [ty, val, n]
|
||||
if (Record.size() != 2)
|
||||
return Error("Invalid GETRESULT record");
|
||||
|
@ -641,7 +641,14 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
|
||||
case Instruction::FCmp:
|
||||
case Instruction::VICmp:
|
||||
case Instruction::VFCmp:
|
||||
Code = bitc::CST_CODE_CE_CMP;
|
||||
if (isa<VectorType>(C->getOperand(0)->getType())
|
||||
&& (CE->getOpcode() == Instruction::ICmp
|
||||
|| CE->getOpcode() == Instruction::FCmp)) {
|
||||
// compare returning vector of Int1Ty
|
||||
assert(0 && "Unsupported constant!");
|
||||
} else {
|
||||
Code = bitc::CST_CODE_CE_CMP;
|
||||
}
|
||||
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(1)));
|
||||
@ -765,7 +772,14 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
|
||||
case Instruction::FCmp:
|
||||
case Instruction::VICmp:
|
||||
case Instruction::VFCmp:
|
||||
Code = bitc::FUNC_CODE_INST_CMP;
|
||||
if (isa<VectorType>(I.getOperand(0)->getType())
|
||||
&& (I.getOpcode() == Instruction::ICmp
|
||||
|| I.getOpcode() == Instruction::FCmp)) {
|
||||
// compare returning vector of Int1Ty
|
||||
Code = bitc::FUNC_CODE_INST_VCMP;
|
||||
} else {
|
||||
Code = bitc::FUNC_CODE_INST_CMP;
|
||||
}
|
||||
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
||||
Vals.push_back(VE.getValueID(I.getOperand(1)));
|
||||
Vals.push_back(cast<CmpInst>(I).getPredicate());
|
||||
|
@ -659,8 +659,21 @@ void Verifier::visitSwitchInst(SwitchInst &SI) {
|
||||
}
|
||||
|
||||
void Verifier::visitSelectInst(SelectInst &SI) {
|
||||
Assert1(SI.getCondition()->getType() == Type::Int1Ty,
|
||||
"Select condition type must be bool!", &SI);
|
||||
if (const VectorType* vt
|
||||
= dyn_cast<VectorType>(SI.getCondition()->getType())) {
|
||||
Assert1( vt->getElementType() == Type::Int1Ty,
|
||||
"Select condition type must be vector of bool!", &SI);
|
||||
if (const VectorType* val_vt
|
||||
= dyn_cast<VectorType>(SI.getTrueValue()->getType())) {
|
||||
Assert1( vt->getNumElements() == val_vt->getNumElements(),
|
||||
"Select vector size != value vector size", &SI);
|
||||
} else {
|
||||
Assert1(0, "Vector select values must have vector types", &SI);
|
||||
}
|
||||
} else {
|
||||
Assert1(SI.getCondition()->getType() == Type::Int1Ty,
|
||||
"Select condition type must be bool!", &SI);
|
||||
}
|
||||
Assert1(SI.getTrueValue()->getType() == SI.getFalseValue()->getType(),
|
||||
"Select values must have identical types!", &SI);
|
||||
Assert1(SI.getTrueValue()->getType() == SI.getType(),
|
||||
@ -1028,7 +1041,7 @@ void Verifier::visitICmpInst(ICmpInst& IC) {
|
||||
Assert1(Op0Ty == Op1Ty,
|
||||
"Both operands to ICmp instruction are not of the same type!", &IC);
|
||||
// Check that the operands are the right type
|
||||
Assert1(Op0Ty->isInteger() || isa<PointerType>(Op0Ty),
|
||||
Assert1(Op0Ty->isIntOrIntVector() || isa<PointerType>(Op0Ty),
|
||||
"Invalid operand types for ICmp instruction", &IC);
|
||||
visitInstruction(IC);
|
||||
}
|
||||
@ -1040,7 +1053,7 @@ void Verifier::visitFCmpInst(FCmpInst& FC) {
|
||||
Assert1(Op0Ty == Op1Ty,
|
||||
"Both operands to FCmp instruction are not of the same type!", &FC);
|
||||
// Check that the operands are the right type
|
||||
Assert1(Op0Ty->isFloatingPoint(),
|
||||
Assert1(Op0Ty->isFPOrFPVector(),
|
||||
"Invalid operand types for FCmp instruction", &FC);
|
||||
visitInstruction(FC);
|
||||
}
|
||||
|
15
test/Assembler/vbool-cmp.ll
Normal file
15
test/Assembler/vbool-cmp.ll
Normal file
@ -0,0 +1,15 @@
|
||||
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | grep {icmp slt}
|
||||
; rudimentary test of fcmp/icmp on vectors returning vector of bool
|
||||
|
||||
define <4 x i1> @ffoo(<4 x float> %a, <4 x float> %b) nounwind {
|
||||
entry:
|
||||
%cmp = fcmp olt <4 x float> %a, %b ; <4 x i1> [#uses=1]
|
||||
ret <4 x i1> %cmp
|
||||
}
|
||||
|
||||
define <4 x i1> @ifoo(<4 x i32> %a, <4 x i32> %b) nounwind {
|
||||
entry:
|
||||
%cmp = icmp slt <4 x i32> %a, %b ; <4 x i1> [#uses=1]
|
||||
ret <4 x i1> %cmp
|
||||
}
|
||||
|
11
test/Assembler/vector-select.ll
Normal file
11
test/Assembler/vector-select.ll
Normal file
@ -0,0 +1,11 @@
|
||||
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | grep select
|
||||
; rudimentary test of select on vectors returning vector of bool
|
||||
|
||||
define <4 x i32> @foo(<4 x i32> %a, <4 x i32> %b,
|
||||
<4 x i1> %cond) nounwind {
|
||||
entry:
|
||||
%cmp = select <4 x i1> %cond, <4 x i32> %a, <4 x i32> %b
|
||||
; <4 x i32> [#uses=1]
|
||||
ret <4 x i32> %cmp
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user