Index: llvm/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/include/llvm/IR/IRBuilder.h +++ llvm/include/llvm/IR/IRBuilder.h @@ -1383,6 +1383,22 @@ return Insert(UnOp, Name); } + Value *CreateNAryOp(unsigned Opc, ArrayRef Ops, + const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + if (Instruction::isBinaryOp(Opc)) { + assert(Ops.size() == 2 && "Invalid number of operands!"); + return CreateBinOp(static_cast(Opc), + Ops[0], Ops[1], Name, FPMathTag); + } + if (Instruction::isUnaryOp(Opc)) { + assert(Ops.size() == 1 && "Invalid number of operands!"); + return CreateUnOp(static_cast(Opc), + Ops[0], Name, FPMathTag); + } + llvm_unreachable("Unexpected opcode!"); + } + //===--------------------------------------------------------------------===// // Instruction creation methods: Memory Instructions //===--------------------------------------------------------------------===// Index: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -3969,6 +3969,7 @@ case Instruction::FAdd: case Instruction::Sub: case Instruction::FSub: + case Instruction::FNeg: case Instruction::Mul: case Instruction::FMul: case Instruction::FDiv: @@ -3979,40 +3980,23 @@ case Instruction::And: case Instruction::Or: case Instruction::Xor: { - // Just widen binops. - auto *BinOp = cast(&I); - setDebugLocFromInst(Builder, BinOp); - - for (unsigned Part = 0; Part < UF; ++Part) { - Value *A = getOrCreateVectorValue(BinOp->getOperand(0), Part); - Value *B = getOrCreateVectorValue(BinOp->getOperand(1), Part); - Value *V = Builder.CreateBinOp(BinOp->getOpcode(), A, B); - - if (BinaryOperator *VecOp = dyn_cast(V)) - VecOp->copyIRFlags(BinOp); - - // Use this vector value for all users of the original instruction. - VectorLoopValueMap.setVectorValue(&I, Part, V); - addMetadata(V, BinOp); - } - - break; - } - case Instruction::FNeg: { - // Just widen unary ops. - auto *UnOp = cast(&I); - setDebugLocFromInst(Builder, UnOp); + // Just widen unops and binops. + setDebugLocFromInst(Builder, &I); for (unsigned Part = 0; Part < UF; ++Part) { - Value *A = getOrCreateVectorValue(UnOp->getOperand(0), Part); - Value *V = Builder.CreateUnOp(UnOp->getOpcode(), A); + SmallVector Ops; + for (unsigned i = 0; i != I.getNumOperands(); ++i) { + Value *V = getOrCreateVectorValue(I.getOperand(i), Part); + Ops.push_back(V); + } + Value *V = Builder.CreateNAryOp(I.getOpcode(), Ops); - if (UnaryOperator *VecOp = dyn_cast(V)) - VecOp->copyIRFlags(UnOp); + if (auto *VecOp = dyn_cast(V)) + VecOp->copyIRFlags(&I); // Use this vector value for all users of the original instruction. VectorLoopValueMap.setVectorValue(&I, Part, V); - addMetadata(V, UnOp); + addMetadata(V, &I); } break;