diff options
author | Dan Gohman <gohman@apple.com> | 2008-09-09 01:02:47 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2008-09-09 01:02:47 +0000 |
commit | f72fb679eff7de84e3e18b75d63a18cb3510bcdd (patch) | |
tree | dbb8edc6c23b2810ff37d055e1f19f2a81bcb504 | |
parent | 3eb594013f666d6af9f943df5fb6ac4d902debee (diff) |
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
-rw-r--r-- | docs/LangRef.html | 71 | ||||
-rw-r--r-- | include/llvm/Bitcode/LLVMBitCodes.h | 4 | ||||
-rw-r--r-- | include/llvm/InstrTypes.h | 8 | ||||
-rw-r--r-- | include/llvm/Instructions.h | 22 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 29 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 29 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 18 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 21 | ||||
-rw-r--r-- | test/Assembler/vbool-cmp.ll | 15 | ||||
-rw-r--r-- | test/Assembler/vector-select.ll | 11 |
10 files changed, 181 insertions, 47 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html index 1beb670765..4921707338 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -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> diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 12607dcd32..d1dcc74437 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -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 diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index 430c772aec..74bb6f53bd 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -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, diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 355103cfa6..8ae9c375fb 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -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)); } + }; //===----------------------------------------------------------------------===// diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 5db76429b5..edc84c1fa1 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -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 } diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 0d6b6f2edb..eeba0e5ed8 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -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"); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index b8aab5acc1..19f5beaf19 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -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()); diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 805fb2564a..af11fce5e7 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -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); } diff --git a/test/Assembler/vbool-cmp.ll b/test/Assembler/vbool-cmp.ll new file mode 100644 index 0000000000..ac8fb29362 --- /dev/null +++ b/test/Assembler/vbool-cmp.ll @@ -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 +} + diff --git a/test/Assembler/vector-select.ll b/test/Assembler/vector-select.ll new file mode 100644 index 0000000000..87af602aaf --- /dev/null +++ b/test/Assembler/vector-select.ll @@ -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 +} + |