diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 60e42b88b91f..6c7c8019c325 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -153,6 +153,8 @@ private: bool translateInsertValue(const User &U); + bool translateSelect(const User &U); + /// Translate return (ret) instruction. /// The target needs to implement CallLowering::lowerReturn for /// this to succeed. @@ -263,7 +265,6 @@ private: bool translateCleanupPad(const User &U) { return false; } bool translateCatchPad(const User &U) { return false; } bool translateFCmp(const User &U) { return false; } - bool translateSelect(const User &U) { return false; } bool translateUserOp1(const User &U) { return false; } bool translateUserOp2(const User &U) { return false; } bool translateVAArg(const User &U) { return false; } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index add109fb9322..70f700103089 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -301,13 +301,21 @@ public: /// \return The newly created instruction. MachineInstrBuilder buildTrunc(LLT Ty, unsigned Res, unsigned Op); - /// Build and insert either a G_ICMP + /// Build and insert a G_ICMP /// /// \pre setBasicBlock or setMI must have been called. /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildICmp(ArrayRef Tys, CmpInst::Predicate Pred, unsigned Res, unsigned Op0, unsigned Op1); + + /// Build and insert a \p Res = G_SELECT { \p Ty, s1 } \p Tst, \p Op0, \p Op1 + /// + /// \pre setBasicBlock or setMI must have been called. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildSelect(LLT Ty, unsigned Res, unsigned Tst, + unsigned Op0, unsigned Op1); }; } // End namespace llvm. diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index f5be5bd9727d..57f74c233ec2 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -191,6 +191,13 @@ def G_ICMP : Instruction { let hasSideEffects = 0; } +// Generic select +def G_SELECT : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$tst, unknown:$src1, unknown:$src2); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Overflow ops //------------------------------------------------------------------------------ diff --git a/llvm/include/llvm/Target/TargetOpcodes.def b/llvm/include/llvm/Target/TargetOpcodes.def index 1a2ea906b73a..682af12a8a14 100644 --- a/llvm/include/llvm/Target/TargetOpcodes.def +++ b/llvm/include/llvm/Target/TargetOpcodes.def @@ -262,6 +262,9 @@ HANDLE_TARGET_OPCODE(G_ASHR) /// Generic integer-base comparison, also applicable to vectors of integers. HANDLE_TARGET_OPCODE(G_ICMP) +/// Generic select. +HANDLE_TARGET_OPCODE(G_SELECT) + /// Generic unsigned add instruction, consuming the normal operands plus a carry /// flag, and similarly producing the result and a carry flag. HANDLE_TARGET_OPCODE(G_UADDE) diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 3c1807fbd2e2..58235c2b823b 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -236,6 +236,13 @@ bool IRTranslator::translateInsertValue(const User &U) { return true; } +bool IRTranslator::translateSelect(const User &U) { + MIRBuilder.buildSelect( + LLT{*U.getType()}, getOrCreateVReg(U), getOrCreateVReg(*U.getOperand(0)), + getOrCreateVReg(*U.getOperand(1)), getOrCreateVReg(*U.getOperand(2))); + return true; +} + bool IRTranslator::translateBitCast(const User &U) { if (LLT{*U.getOperand(0)->getType()} == LLT{*U.getType()}) { unsigned &Reg = ValToVReg[&U]; diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index bd66a28bdc22..0d2fae659e81 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -216,3 +216,13 @@ MachineInstrBuilder MachineIRBuilder::buildICmp(ArrayRef Tys, .addUse(Op0) .addUse(Op1); } + +MachineInstrBuilder MachineIRBuilder::buildSelect(LLT Ty, unsigned Res, + unsigned Tst, + unsigned Op0, unsigned Op1) { + return buildInstr(TargetOpcode::G_SELECT, {Ty, LLT::scalar(1)}) + .addDef(Res) + .addUse(Tst) + .addUse(Op0) + .addUse(Op1); +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index 0a6de5f45cb5..39ea0bc53384 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -729,3 +729,14 @@ define void @test_insertvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) { store %struct.nested %res, %struct.nested* %addr ret void } + +; CHECK-LABEL: name: test_select +; CHECK: [[TST:%[0-9]+]](1) = COPY %w0 +; CHECK: [[LHS:%[0-9]+]](32) = COPY %w1 +; CHECK: [[RHS:%[0-9]+]](32) = COPY %w2 +; CHECK: [[RES:%[0-9]+]](32) = G_SELECT { s32, s1 } [[TST]], [[LHS]], [[RHS]] +; CHECK: %w0 = COPY [[RES]] +define i32 @test_select(i1 %tst, i32 %lhs, i32 %rhs) { + %res = select i1 %tst, i32 %lhs, i32 %rhs + ret i32 %res +}