From 094c72f8b4303b740c12b5555c9ef02f91cbced3 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Fri, 11 Oct 2019 20:22:47 +0000 Subject: [PATCH] [MachineIRBuilder] Fix an assertion failure with buildMerge Teach buildMerge how to deal with scalar to vector kind of requests. Prior to this patch, buildMerge would issue either a G_MERGE_VALUES when all the vregs are scalars or a G_CONCAT_VECTORS when the destination vreg is a vector. G_CONCAT_VECTORS was actually not the proper instruction when the source vregs were scalars and the compiler would assert that the sources must be vectors. Instead we want is to issue a G_BUILD_VECTOR when we are in this situation. This patch fixes that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374588 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 7 +++- .../GlobalISel/MachineIRBuilderTest.cpp | 39 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 8a96a900aa0..9bbff490ea3 100644 --- a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -1063,8 +1063,11 @@ MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opc, "input operands do not cover output register"); if (SrcOps.size() == 1) return buildCast(DstOps[0], SrcOps[0]); - if (DstOps[0].getLLTTy(*getMRI()).isVector()) - return buildInstr(TargetOpcode::G_CONCAT_VECTORS, DstOps, SrcOps); + if (DstOps[0].getLLTTy(*getMRI()).isVector()) { + if (SrcOps[0].getLLTTy(*getMRI()).isVector()) + return buildInstr(TargetOpcode::G_CONCAT_VECTORS, DstOps, SrcOps); + return buildInstr(TargetOpcode::G_BUILD_VECTOR, DstOps, SrcOps); + } break; } case TargetOpcode::G_EXTRACT_VECTOR_ELT: { diff --git a/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp b/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp index 72a85db9461..f39c28dc648 100644 --- a/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp +++ b/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp @@ -314,3 +314,42 @@ TEST_F(GISelMITest, BuildAtomicRMW) { EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; } + +TEST_F(GISelMITest, BuildMerge) { + setUp(); + if (!TM) + return; + + LLT S32 = LLT::scalar(32); + Register RegC0 = B.buildConstant(S32, 0)->getOperand(0).getReg(); + Register RegC1 = B.buildConstant(S32, 1)->getOperand(0).getReg(); + Register RegC2 = B.buildConstant(S32, 2)->getOperand(0).getReg(); + Register RegC3 = B.buildConstant(S32, 3)->getOperand(0).getReg(); + + // Merging plain constants as one big blob of bit should produce a + // G_MERGE_VALUES. + B.buildMerge(LLT::scalar(128), {RegC0, RegC1, RegC2, RegC3}); + // Merging plain constants to a vector should produce a G_BUILD_VECTOR. + LLT V2x32 = LLT::vector(2, 32); + Register RegC0C1 = + B.buildMerge(V2x32, {RegC0, RegC1})->getOperand(0).getReg(); + Register RegC2C3 = + B.buildMerge(V2x32, {RegC2, RegC3})->getOperand(0).getReg(); + // Merging vector constants to a vector should produce a G_CONCAT_VECTORS. + B.buildMerge(LLT::vector(4, 32), {RegC0C1, RegC2C3}); + // Merging vector constants to a plain type is not allowed. + // Nothing else to test. + + auto CheckStr = R"( + ; CHECK: [[C0:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK: {{%[0-9]+}}:_(s128) = G_MERGE_VALUES [[C0]]:_(s32), [[C1]]:_(s32), [[C2]]:_(s32), [[C3]]:_(s32) + ; CHECK: [[LOW2x32:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C0]]:_(s32), [[C1]]:_(s32) + ; CHECK: [[HIGH2x32:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C2]]:_(s32), [[C3]]:_(s32) + ; CHECK: {{%[0-9]+}}:_(<4 x s32>) = G_CONCAT_VECTORS [[LOW2x32]]:_(<2 x s32>), [[HIGH2x32]]:_(<2 x s32>) + )"; + + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} -- 2.50.0