#include "llvm/CodeGen/GlobalISel/Legalizer.h"
#include "GISelMITest.h"
#include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
#define DEBUG_TYPE "legalizer-test"
using namespace LegalizeActions;
using namespace LegalizeMutations;
using namespace LegalityPredicates;
namespace {
::testing::AssertionResult isNullMIPtr(const MachineInstr *MI) {
if (MI == nullptr)
return ::testing::AssertionSuccess();
std::string MIBuffer;
raw_string_ostream MISStream(MIBuffer);
MI->print(MISStream, true, false,
false, false);
return ::testing::AssertionFailure()
<< "unable to legalize instruction: " << MISStream.str();
}
DefineLegalizerInfo(ALegalizer, {
auto p0 = LLT::pointer(0, 64);
auto s8 = LLT::scalar(8);
auto v2s8 = LLT::fixed_vector(2, 8);
auto v2s16 = LLT::fixed_vector(2, 16);
getActionDefinitionsBuilder(G_LOAD)
.legalForTypesWithMemDesc({{s16, p0, s8, 8}})
.scalarize(0)
.clampScalar(0, s16, s16);
getActionDefinitionsBuilder(G_PTR_ADD).legalFor({{p0, s64}});
getActionDefinitionsBuilder(G_CONSTANT).legalFor({s32, s64});
getActionDefinitionsBuilder(G_BUILD_VECTOR)
.legalFor({{v2s16, s16}})
.clampScalar(1, s16, s16);
getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC).legalFor({{v2s8, s16}});
getActionDefinitionsBuilder(G_ANYEXT).legalFor({{s32, s16}});
getActionDefinitionsBuilder(G_ZEXT).legalFor({{s32, s16}});
getActionDefinitionsBuilder(G_SEXT).legalFor({{s32, s16}});
getActionDefinitionsBuilder(G_AND).legalFor({s32});
getActionDefinitionsBuilder(G_SEXT_INREG).lower();
getActionDefinitionsBuilder(G_ASHR).legalFor({{s32, s32}});
getActionDefinitionsBuilder(G_SHL).legalFor({{s32, s32}});
})
TEST_F(AArch64GISelMITest, BasicLegalizerTest) {
StringRef MIRString = R"(
%vptr:_(p0) = COPY $x4
%v:_(<2 x s8>) = G_LOAD %vptr:_(p0) :: (load (<2 x s8>), align 1)
$h4 = COPY %v:_(<2 x s8>)
)";
setUp(MIRString.rtrim(' '));
if (!TM)
return;
ALegalizerInfo LI(MF->getSubtarget());
LostDebugLocObserver LocObserver(DEBUG_TYPE);
Legalizer::MFResult Result = Legalizer::legalizeMachineFunction(
*MF, LI, {&LocObserver}, LocObserver, B);
EXPECT_TRUE(isNullMIPtr(Result.FailedOn));
EXPECT_TRUE(Result.Changed);
StringRef CheckString = R"(
CHECK: %vptr:_(p0) = COPY $x4
CHECK-NEXT: [[LOAD_0:%[0-9]+]]:_(s16) = G_LOAD %vptr:_(p0) :: (load (s8))
CHECK-NEXT: [[OFFSET_1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
CHECK-NEXT: [[VPTR_1:%[0-9]+]]:_(p0) = G_PTR_ADD %vptr:_, [[OFFSET_1]]:_(s64)
CHECK-NEXT: [[LOAD_1:%[0-9]+]]:_(s16) = G_LOAD [[VPTR_1]]:_(p0) :: (load (s8) from unknown-address + 1)
CHECK-NEXT: %v:_(<2 x s8>) = G_BUILD_VECTOR_TRUNC [[LOAD_0]]:_(s16), [[LOAD_1]]:_(s16)
CHECK-NEXT: $h4 = COPY %v:_(<2 x s8>)
)";
EXPECT_TRUE(CheckMachineFunction(*MF, CheckString)) << *MF;
}
TEST_F(AArch64GISelMITest, UnorderedArtifactCombiningTest) {
StringRef MIRString = R"(
%vptr:_(p0) = COPY $x4
%v:_(<2 x s8>) = G_LOAD %vptr:_(p0) :: (load (<2 x s8>), align 1)
%v0:_(s8), %v1:_(s8) = G_UNMERGE_VALUES %v:_(<2 x s8>)
%v0_ext:_(s16) = G_ANYEXT %v0:_(s8)
$h4 = COPY %v0_ext:_(s16)
)";
setUp(MIRString.rtrim(' '));
if (!TM)
return;
ALegalizerInfo LI(MF->getSubtarget());
LostDebugLocObserver LocObserver(DEBUG_TYPE);
Legalizer::MFResult Result = Legalizer::legalizeMachineFunction(
*MF, LI, {&LocObserver}, LocObserver, B);
EXPECT_TRUE(isNullMIPtr(Result.FailedOn));
EXPECT_TRUE(Result.Changed);
StringRef CheckString = R"(
CHECK: %vptr:_(p0) = COPY $x4
CHECK-NEXT: [[LOAD_0:%[0-9]+]]:_(s16) = G_LOAD %vptr:_(p0) :: (load (s8))
CHECK: $h4 = COPY [[LOAD_0]]:_(s16)
)";
EXPECT_TRUE(CheckMachineFunction(*MF, CheckString)) << *MF;
}
TEST_F(AArch64GISelMITest, UnorderedArtifactCombiningManyCopiesTest) {
StringRef MIRString = R"(
%vptr:_(p0) = COPY $x4
%v:_(<2 x s8>) = G_LOAD %vptr:_(p0) :: (load (<2 x s8>), align 1)
%vc0:_(<2 x s8>) = COPY %v:_(<2 x s8>)
%vc1:_(<2 x s8>) = COPY %v:_(<2 x s8>)
%vc00:_(s8), %vc01:_(s8) = G_UNMERGE_VALUES %vc0:_(<2 x s8>)
%vc10:_(s8), %vc11:_(s8) = G_UNMERGE_VALUES %vc1:_(<2 x s8>)
%v0t:_(s8) = COPY %vc00:_(s8)
%v0:_(s8) = COPY %v0t:_(s8)
%v1t:_(s8) = COPY %vc11:_(s8)
%v1:_(s8) = COPY %v1t:_(s8)
%v0_zext:_(s32) = G_ZEXT %v0:_(s8)
%v1_sext:_(s32) = G_SEXT %v1:_(s8)
$w4 = COPY %v0_zext:_(s32)
$w5 = COPY %v1_sext:_(s32)
)";
setUp(MIRString.rtrim(' '));
if (!TM)
return;
ALegalizerInfo LI(MF->getSubtarget());
LostDebugLocObserver LocObserver(DEBUG_TYPE);
Legalizer::MFResult Result = Legalizer::legalizeMachineFunction(
*MF, LI, {&LocObserver}, LocObserver, B);
EXPECT_TRUE(isNullMIPtr(Result.FailedOn));
EXPECT_TRUE(Result.Changed);
StringRef CheckString = R"(
CHECK: %vptr:_(p0) = COPY $x4
CHECK-NEXT: [[LOAD_0:%[0-9]+]]:_(s16) = G_LOAD %vptr:_(p0) :: (load (s8))
CHECK-NEXT: [[OFFSET_1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
CHECK-NEXT: [[VPTR_1:%[0-9]+]]:_(p0) = G_PTR_ADD %vptr:_, [[OFFSET_1]]:_(s64)
CHECK-NEXT: [[LOAD_1:%[0-9]+]]:_(s16) = G_LOAD [[VPTR_1]]:_(p0) :: (load (s8) from unknown-address + 1)
CHECK-NEXT: [[FF_MASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
CHECK-NEXT: [[V0_EXT:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD_0]]:_(s16)
CHECK-NEXT: %v0_zext:_(s32) = G_AND [[V0_EXT]]:_, [[FF_MASK]]:_
CHECK-NEXT: [[V1_EXT:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD_1]]:_(s16)
CHECK-NEXT: [[SHAMNT:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
CHECK-NEXT: [[V1_SHL:%[0-9]+]]:_(s32) = G_SHL [[V1_EXT]]:_, [[SHAMNT]]:_(s32)
CHECK-NEXT: %v1_sext:_(s32) = G_ASHR [[V1_SHL]]:_, [[SHAMNT]]:_(s32)
CHECK-NEXT: $w4 = COPY %v0_zext:_(s32)
CHECK-NEXT: $w5 = COPY %v1_sext:_(s32)
)";
EXPECT_TRUE(CheckMachineFunction(*MF, CheckString)) << *MF;
}
}