[llvm-commits] [llvm] r55969 - in /llvm/trunk: docs/LangRef.html include/llvm/Bitcode/LLVMBitCodes.h include/llvm/InstrTypes.h include/llvm/Instructions.h lib/AsmParser/llvmAsmParser.y lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/VMCore/Verifier.cpp test/Assembler/vbool-cmp.ll test/Assembler/vector-select.ll

Dan Gohman gohman at apple.com
Mon Sep 8 18:02:47 PDT 2008


Author: djg
Date: Mon Sep  8 20:02:47 2008
New Revision: 55969

URL: http://llvm.org/viewvc/llvm-project?rev=55969&view=rev
Log:
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!

Added:
    llvm/trunk/test/Assembler/vbool-cmp.ll
    llvm/trunk/test/Assembler/vector-select.ll
Modified:
    llvm/trunk/docs/LangRef.html
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/InstrTypes.h
    llvm/trunk/include/llvm/Instructions.h
    llvm/trunk/lib/AsmParser/llvmAsmParser.y
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/VMCore/Verifier.cpp

Modified: llvm/trunk/docs/LangRef.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/docs/LangRef.html (original)
+++ llvm/trunk/docs/LangRef.html Mon Sep  8 20:02:47 2008
@@ -3846,11 +3846,12 @@
 </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&gt}: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 @@
   <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 @@
 </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 @@
 </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&gt}: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 @@
 </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 @@
 
 <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 @@
   <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 @@
 <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&gt}
 </pre>
 
 <h5>Overview:</h5>
@@ -4154,18 +4176,25 @@
 <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>
 

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Mon Sep  8 20:02:47 2008
@@ -205,7 +205,9 @@
     // 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

Modified: llvm/trunk/include/llvm/InstrTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InstrTypes.h?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/include/llvm/InstrTypes.h (original)
+++ llvm/trunk/include/llvm/InstrTypes.h Mon Sep  8 20:02:47 2008
@@ -18,6 +18,7 @@
 
 #include "llvm/Instruction.h"
 #include "llvm/OperandTraits.h"
+#include "llvm/DerivedTypes.h"
 
 namespace llvm {
 
@@ -732,6 +733,13 @@
   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, 

Modified: llvm/trunk/include/llvm/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Instructions.h (original)
+++ llvm/trunk/include/llvm/Instructions.h Mon Sep  8 20:02:47 2008
@@ -621,7 +621,8 @@
     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 @@
     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 @@
     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 @@
     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 @@
   static inline bool classof(const Value *V) {
     return isa<Instruction>(V) && classof(cast<Instruction>(V));
   }
+
 };
 
 //===----------------------------------------------------------------------===//
@@ -773,14 +776,15 @@
     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 @@
     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 @@
   static inline bool classof(const Value *V) {
     return isa<Instruction>(V) && classof(cast<Instruction>(V));
   }
+  
 };
 
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/AsmParser/llvmAsmParser.y
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/llvmAsmParser.y?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/lib/AsmParser/llvmAsmParser.y (original)
+++ llvm/trunk/lib/AsmParser/llvmAsmParser.y Mon Sep  8 20:02:47 2008
@@ -1102,7 +1102,7 @@
 %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 @@
   | 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 @@
   | 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 @@
     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 @@
     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 @@
     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
   }

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Mon Sep  8 20:02:47 2008
@@ -1499,8 +1499,19 @@
       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 @@
         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");

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Mon Sep  8 20:02:47 2008
@@ -641,7 +641,14 @@
       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 @@
   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());

Modified: llvm/trunk/lib/VMCore/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=55969&r1=55968&r2=55969&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Verifier.cpp (original)
+++ llvm/trunk/lib/VMCore/Verifier.cpp Mon Sep  8 20:02:47 2008
@@ -659,8 +659,21 @@
 }
 
 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 @@
   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 @@
   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);
 }

Added: llvm/trunk/test/Assembler/vbool-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/vbool-cmp.ll?rev=55969&view=auto

==============================================================================
--- llvm/trunk/test/Assembler/vbool-cmp.ll (added)
+++ llvm/trunk/test/Assembler/vbool-cmp.ll Mon Sep  8 20:02:47 2008
@@ -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
+}
+

Added: llvm/trunk/test/Assembler/vector-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/vector-select.ll?rev=55969&view=auto

==============================================================================
--- llvm/trunk/test/Assembler/vector-select.ll (added)
+++ llvm/trunk/test/Assembler/vector-select.ll Mon Sep  8 20:02:47 2008
@@ -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
+}
+





More information about the llvm-commits mailing list