From 5e24d2fee2bd8e06d7cc425e4e7cff99fcd47378 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 23 Jun 2017 16:15:37 +0000 Subject: [PATCH] GlobalISel: convert buildSequence to use non-deprecated instructions. G_SEQUENCE is going away soon so as a first step the MachineIRBuilder needs to be taught how to emulate it with alternatives. We use G_MERGE_VALUES where possible, and a sequence of G_INSERTs if not. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306119 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../CodeGen/GlobalISel/MachineIRBuilder.h | 31 ++++------------- lib/CodeGen/GlobalISel/IRTranslator.cpp | 2 +- lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 34 ++++++++++++++----- .../AArch64/GlobalISel/arm64-irtranslator.ll | 24 +++++++++---- .../AArch64/GlobalISel/call-translator.ll | 2 +- .../ARM/GlobalISel/arm-irtranslator.ll | 7 ++-- 6 files changed, 57 insertions(+), 43 deletions(-) diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 4e7b8350038..b7215da0fb2 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -471,10 +471,12 @@ public: /// Build and insert \p Res = IMPLICIT_DEF. MachineInstrBuilder buildUndef(unsigned Dst); - /// Build and insert \p Res = G_SEQUENCE \p Op0, \p Idx0... + /// Build and insert instructions to put \p Ops together at the specified p + /// Indices to form a larger register. /// - /// G_SEQUENCE inserts each element of Ops into an IMPLICIT_DEF register, - /// where each entry starts at the bit-index specified by \p Indices. + /// If the types of the input registers are uniform and cover the entirity of + /// \p Res then a G_MERGE_VALUES will be produced. Otherwise an IMPLICIT_DEF + /// followed by a sequence of G_INSERT instructions. /// /// \pre setBasicBlock or setMI must have been called. /// \pre The final element of the sequence must not extend past the end of the @@ -484,9 +486,8 @@ public: /// \pre \p Indices must be in ascending order of bit position. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildSequence(unsigned Res, - ArrayRef Ops, - ArrayRef Indices); + void buildSequence(unsigned Res, ArrayRef Ops, + ArrayRef Indices); /// Build and insert \p Res = G_MERGE_VALUES \p Op0, ... /// @@ -513,24 +514,6 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildUnmerge(ArrayRef Res, unsigned Op); - void addUsesWithIndices(MachineInstrBuilder MIB) {} - - template - void addUsesWithIndices(MachineInstrBuilder MIB, unsigned Reg, - unsigned BitIndex, ArgTys... Args) { - MIB.addUse(Reg).addImm(BitIndex); - addUsesWithIndices(MIB, Args...); - } - - template - MachineInstrBuilder buildSequence(unsigned Res, unsigned Op, - unsigned Index, ArgTys... Args) { - MachineInstrBuilder MIB = - buildInstr(TargetOpcode::G_SEQUENCE).addDef(Res); - addUsesWithIndices(MIB, Op, Index, Args...); - return MIB; - } - MachineInstrBuilder buildInsert(unsigned Res, unsigned Src, unsigned Op, unsigned Index); diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index 7fefbf90922..239bad2f535 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -582,7 +582,7 @@ bool IRTranslator::translateOverflowIntrinsic(const CallInst &CI, unsigned Op, MIB.addUse(Zero); } - MIRBuilder.buildSequence(getOrCreateVReg(CI), Res, 0, Overflow, Width); + MIRBuilder.buildSequence(getOrCreateVReg(CI), {Res, Overflow}, {0, Width}); return true; } diff --git a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 79d312fb52c..3c70013ea29 100644 --- a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -425,10 +425,8 @@ MachineInstrBuilder MachineIRBuilder::buildExtract(unsigned Res, unsigned Src, .addImm(Index); } -MachineInstrBuilder -MachineIRBuilder::buildSequence(unsigned Res, - ArrayRef Ops, - ArrayRef Indices) { +void MachineIRBuilder::buildSequence(unsigned Res, ArrayRef Ops, + ArrayRef Indices) { #ifndef NDEBUG assert(Ops.size() == Indices.size() && "incompatible args"); assert(!Ops.empty() && "invalid trivial sequence"); @@ -440,13 +438,31 @@ MachineIRBuilder::buildSequence(unsigned Res, assert(MRI->getType(Op).isValid() && "invalid operand type"); #endif - MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE); - MIB.addDef(Res); + LLT ResTy = MRI->getType(Res); + LLT OpTy = MRI->getType(Ops[0]); + unsigned OpSize = OpTy.getSizeInBits(); + bool MaybeMerge = true; for (unsigned i = 0; i < Ops.size(); ++i) { - MIB.addUse(Ops[i]); - MIB.addImm(Indices[i]); + if (MRI->getType(Ops[i]) != OpTy || Indices[i] != i * OpSize) { + MaybeMerge = false; + break; + } + } + + if (MaybeMerge && Ops.size() * OpSize == ResTy.getSizeInBits()) { + buildMerge(Res, Ops); + return; + } + + unsigned ResIn = MRI->createGenericVirtualRegister(ResTy); + buildUndef(ResIn); + + for (unsigned i = 0; i < Ops.size(); ++i) { + unsigned ResOut = + i + 1 == Ops.size() ? Res : MRI->createGenericVirtualRegister(ResTy); + buildInsert(ResOut, ResIn, Ops[i], Indices[i]); + ResIn = ResOut; } - return MIB; } MachineInstrBuilder MachineIRBuilder::buildUndef(unsigned Res) { diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index e07d5ad8410..81b42d06481 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -807,7 +807,9 @@ define float @test_frem(float %arg1, float %arg2) { ; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1 ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_SADDO [[LHS]], [[RHS]] -; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32 +; CHECK: [[TMP:%[0-9]+]](s64) = IMPLICIT_DEF +; CHECK: [[TMP1:%[0-9]+]](s64) = G_INSERT [[TMP]], [[VAL]](s32), 0 +; CHECK: [[RES:%[0-9]+]](s64) = G_INSERT [[TMP1]], [[OVERFLOW]](s1), 32 ; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0) declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) define void @test_sadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { @@ -822,7 +824,9 @@ define void @test_sadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT i1 false ; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_UADDE [[LHS]], [[RHS]], [[ZERO]] -; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32 +; CHECK: [[TMP:%[0-9]+]](s64) = IMPLICIT_DEF +; CHECK: [[TMP1:%[0-9]+]](s64) = G_INSERT [[TMP]], [[VAL]](s32), 0 +; CHECK: [[RES:%[0-9]+]](s64) = G_INSERT [[TMP1]], [[OVERFLOW]](s1), 32 ; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0) declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) define void @test_uadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { @@ -836,7 +840,9 @@ define void @test_uadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { ; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1 ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_SSUBO [[LHS]], [[RHS]] -; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32 +; CHECK: [[TMP:%[0-9]+]](s64) = IMPLICIT_DEF +; CHECK: [[TMP1:%[0-9]+]](s64) = G_INSERT [[TMP]], [[VAL]](s32), 0 +; CHECK: [[RES:%[0-9]+]](s64) = G_INSERT [[TMP1]], [[OVERFLOW]](s1), 32 ; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0) declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) define void @test_ssub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) { @@ -851,7 +857,9 @@ define void @test_ssub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) { ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT i1 false ; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_USUBE [[LHS]], [[RHS]], [[ZERO]] -; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32 +; CHECK: [[TMP:%[0-9]+]](s64) = IMPLICIT_DEF +; CHECK: [[TMP1:%[0-9]+]](s64) = G_INSERT [[TMP]], [[VAL]](s32), 0 +; CHECK: [[RES:%[0-9]+]](s64) = G_INSERT [[TMP1]], [[OVERFLOW]](s1), 32 ; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0) declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) define void @test_usub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) { @@ -865,7 +873,9 @@ define void @test_usub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) { ; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1 ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_SMULO [[LHS]], [[RHS]] -; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32 +; CHECK: [[TMP:%[0-9]+]](s64) = IMPLICIT_DEF +; CHECK: [[TMP1:%[0-9]+]](s64) = G_INSERT [[TMP]], [[VAL]](s32), 0 +; CHECK: [[RES:%[0-9]+]](s64) = G_INSERT [[TMP1]], [[OVERFLOW]](s1), 32 ; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0) declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) define void @test_smul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { @@ -879,7 +889,9 @@ define void @test_smul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { ; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1 ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_UMULO [[LHS]], [[RHS]] -; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32 +; CHECK: [[TMP:%[0-9]+]](s64) = IMPLICIT_DEF +; CHECK: [[TMP1:%[0-9]+]](s64) = G_INSERT [[TMP]], [[VAL]](s32), 0 +; CHECK: [[RES:%[0-9]+]](s64) = G_INSERT [[TMP1]], [[OVERFLOW]](s1), 32 ; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0) declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) define void @test_umul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { diff --git a/test/CodeGen/AArch64/GlobalISel/call-translator.ll b/test/CodeGen/AArch64/GlobalISel/call-translator.ll index e923a0b2847..0e593fdb7b8 100644 --- a/test/CodeGen/AArch64/GlobalISel/call-translator.ll +++ b/test/CodeGen/AArch64/GlobalISel/call-translator.ll @@ -113,7 +113,7 @@ define {double, i64, i32} @test_struct_return({double, i64, i32}* %addr) { ; CHECK: [[E1:%[0-9]+]](s64) = COPY %x1 ; CHECK: [[E2:%[0-9]+]](s64) = COPY %x2 ; CHECK: [[E3:%[0-9]+]](s64) = COPY %x3 -; CHECK: [[RES:%[0-9]+]](s256) = G_SEQUENCE [[E0]](s64), 0, [[E1]](s64), 64, [[E2]](s64), 128, [[E3]](s64), 192 +; CHECK: [[RES:%[0-9]+]](s256) = G_MERGE_VALUES [[E0]](s64), [[E1]](s64), [[E2]](s64), [[E3]](s64) ; CHECK: G_EXTRACT [[RES]](s256), 64 declare [4 x i64] @arr_callee([4 x i64]) define i64 @test_arr_call([4 x i64]* %addr) { diff --git a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll index 6663a9210b8..0ff8d52e94c 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -1009,8 +1009,11 @@ define i32 @test_constantstruct_v2s32_s32_s32() { ; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C2]](s32) ; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 ; CHECK: [[C4:%[0-9]+]](s32) = G_CONSTANT i32 4 -; CHECK: [[CS:%[0-9]+]](s128) = G_SEQUENCE [[VEC]](<2 x s32>), 0, [[C3]](s32), 64, [[C4]](s32), 96 -; CHECK: [[EXT:%[0-9]+]](<2 x s32>) = G_EXTRACT [[CS]](s128), 0 +; CHECK: [[C5:%[0-9]+]](s128) = IMPLICIT_DEF +; CHECK: [[C6:%[0-9]+]](s128) = G_INSERT [[C5]], [[VEC]](<2 x s32>), 0 +; CHECK: [[C7:%[0-9]+]](s128) = G_INSERT [[C6]], [[C3]](s32), 64 +; CHECK: [[C8:%[0-9]+]](s128) = G_INSERT [[C7]], [[C4]](s32), 96 +; CHECK: [[EXT:%[0-9]+]](<2 x s32>) = G_EXTRACT [[C8]](s128), 0 ; CHECK: G_EXTRACT_VECTOR_ELT [[EXT]](<2 x s32>) %vec = extractvalue %struct.v2s32.s32.s32 {<2 x i32>, i32 3, i32 4}, 0 %elt = extractelement <2 x i32> %vec, i32 0 -- 2.50.1