Index: lib/Transforms/Vectorize/LoopVectorizationPlanner.h =================================================================== --- lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -139,6 +139,27 @@ return createInstruction(Instruction::BinaryOps::Or, {LHS, RHS}); } + /// Create a VPCmpInst with \p LeftOp and \p RightOp as operands and \p Pred + /// as predicate. + VPCmpInst *createCmpInst(VPValue *LeftOp, VPValue *RightOp, + CmpInst::Predicate Pred) { + assert(LeftOp && RightOp && "VPCmpInst's operands can't be null!"); + VPCmpInst *Instr = new VPCmpInst(LeftOp, RightOp, Pred); + if (BB) + BB->insert(Instr, InsertPt); + return Instr; + } + + /// Create a VPCmpInst with \p LeftOp and \p RightOp as operands and \p CI's + /// predicate as predicate. \p CI is also set as underlying Instruction. + VPCmpInst *createCmpInst(VPValue *LeftOp, VPValue *RightOp, CmpInst *CI) { + assert(CI && "CI can't be null!"); + assert(LeftOp && RightOp && "VPCmpInst's operands can't be null!"); + VPCmpInst *VPCI = createCmpInst(LeftOp, RightOp, CI->getPredicate()); + VPCI->setUnderlyingValue(CI); + return VPCI; + } + //===--------------------------------------------------------------------===// // RAII helpers. //===--------------------------------------------------------------------===// Index: lib/Transforms/Vectorize/VPlan.h =================================================================== --- lib/Transforms/Vectorize/VPlan.h +++ lib/Transforms/Vectorize/VPlan.h @@ -645,6 +645,50 @@ void print(raw_ostream &O) const; }; +/// Concrete class for comparison VPInstruction. Represents both integer and +/// floating point comparisons. +class VPCmpInst : public VPInstruction { +public: + typedef CmpInst::Predicate Predicate; + + /// Create VPCmpInst with operands \p LHS and \p RHS and predicate \p Pred. + VPCmpInst(VPValue *LHS, VPValue *RHS, Predicate Pred) + : VPInstruction(inferOpcodeFromPredicate(Pred), + ArrayRef({LHS, RHS})), + Pred(Pred) { + assert(LHS && RHS && "VPCmpInst's operands can't be null!"); + } + + /// Return the predicate for this comparison VPInstruction. + Predicate getPredicate() const { return Pred; } + + /// Methods for supporting type inquiry through isa, cast, and dyn_cast: + static bool classof(const VPInstruction *VPI) { + return VPI->getOpcode() == Instruction::ICmp || + VPI->getOpcode() == Instruction::FCmp; + } + static bool classof(const VPValue *V) { + return isa(V) && classof(cast(V)); + } + static bool classof(const VPRecipeBase *V) { + return isa(V) && classof(cast(V)); + } + +private: + // Predicate of the comparison. + Predicate Pred; + + // Return the opcode that corresponds to predicate \p Pred. + unsigned inferOpcodeFromPredicate(Predicate Pred) { + // Infer Opcode from Pred. + if (CmpInst::isIntPredicate(Pred)) + return Instruction::ICmp; + if (CmpInst::isFPPredicate(Pred)) + return Instruction::FCmp; + llvm_unreachable("Integer/Float predicate expected!"); + } +}; + /// VPWidenRecipe is a recipe for producing a copy of vector type for each /// Instruction in its ingredients independently, in order. This recipe covers /// most of the traditional vectorization cases where each ingredient transforms Index: lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp =================================================================== --- lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp +++ lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp @@ -222,10 +222,14 @@ for (Value *Op : Inst->operands()) VPOperands.push_back(getOrCreateVPOperand(Op)); - // Build VPInstruction for any arbitraty Instruction without specific - // representation in VPlan. - NewVPInst = cast( - VPIRBuilder.createNaryOp(Inst->getOpcode(), VPOperands, Inst)); + if (auto *CI = dyn_cast(Inst)) { + assert(VPOperands.size() == 2 && "Expected 2 operands in CmpInst."); + NewVPInst = VPIRBuilder.createCmpInst(VPOperands[0], VPOperands[1], CI); + } else + // Build VPInstruction for any arbitraty Instruction without specific + // representation in VPlan. + NewVPInst = cast( + VPIRBuilder.createNaryOp(Inst->getOpcode(), VPOperands, Inst)); } IRDef2VPValue[Inst] = NewVPInst; Index: unittests/Transforms/Vectorize/VPlanHCFGTest.cpp =================================================================== --- unittests/Transforms/Vectorize/VPlanHCFGTest.cpp +++ unittests/Transforms/Vectorize/VPlanHCFGTest.cpp @@ -82,9 +82,10 @@ EXPECT_EQ(2u, IndvarAdd->getNumOperands()); EXPECT_EQ(Phi, IndvarAdd->getOperand(0)); - VPInstruction *ICmp = dyn_cast(&*Iter++); + VPCmpInst *ICmp = dyn_cast(&*Iter++); EXPECT_EQ(Instruction::ICmp, ICmp->getOpcode()); EXPECT_EQ(2u, ICmp->getNumOperands()); + EXPECT_EQ(CmpInst::ICMP_NE, ICmp->getPredicate()); EXPECT_EQ(IndvarAdd, ICmp->getOperand(0)); EXPECT_EQ(VecBB->getCondBit(), ICmp);