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 /lib | |
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
Diffstat (limited to 'lib')
-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 |
4 files changed, 80 insertions, 17 deletions
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); } |