1 //===- CSETest.cpp -----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "GISelMITest.h"
10 #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
11 
12 namespace {
13 
14 TEST_F(GISelMITest, TestCSE) {
15   if (!TM)
16     return;
17 
18   LLT s16{LLT::scalar(16)};
19   LLT s32{LLT::scalar(32)};
20   auto MIBInput = B.buildInstr(TargetOpcode::G_TRUNC, {s16}, {Copies[0]});
21   auto MIBInput1 = B.buildInstr(TargetOpcode::G_TRUNC, {s16}, {Copies[1]});
22   auto MIBAdd = B.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
23   GISelCSEInfo CSEInfo;
24   CSEInfo.setCSEConfig(make_unique<CSEConfigFull>());
25   CSEInfo.analyze(*MF);
26   B.setCSEInfo(&CSEInfo);
27   CSEMIRBuilder CSEB(B.getState());
28 
29   CSEB.setInsertPt(*EntryMBB, EntryMBB->begin());
30   unsigned AddReg = MRI->createGenericVirtualRegister(s16);
31   auto MIBAddCopy =
32       CSEB.buildInstr(TargetOpcode::G_ADD, {AddReg}, {MIBInput, MIBInput});
33   EXPECT_EQ(MIBAddCopy->getOpcode(), TargetOpcode::COPY);
34   auto MIBAdd2 =
35       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
36   EXPECT_TRUE(&*MIBAdd == &*MIBAdd2);
37   auto MIBAdd4 =
38       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
39   EXPECT_TRUE(&*MIBAdd == &*MIBAdd4);
40   auto MIBAdd5 =
41       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput1});
42   EXPECT_TRUE(&*MIBAdd != &*MIBAdd5);
43 
44   // Try building G_CONSTANTS.
45   auto MIBCst = CSEB.buildConstant(s32, 0);
46   auto MIBCst1 = CSEB.buildConstant(s32, 0);
47   EXPECT_TRUE(&*MIBCst == &*MIBCst1);
48   // Try the CFing of BinaryOps.
49   auto MIBCF1 = CSEB.buildInstr(TargetOpcode::G_ADD, {s32}, {MIBCst, MIBCst});
50   EXPECT_TRUE(&*MIBCF1 == &*MIBCst);
51 
52   // Try out building FCONSTANTs.
53   auto MIBFP0 = CSEB.buildFConstant(s32, 1.0);
54   auto MIBFP0_1 = CSEB.buildFConstant(s32, 1.0);
55   EXPECT_TRUE(&*MIBFP0 == &*MIBFP0_1);
56   CSEInfo.print();
57 
58   // Make sure buildConstant with a vector type doesn't crash, and the elements
59   // CSE.
60   auto Splat0 = CSEB.buildConstant(LLT::vector(2, s32), 0);
61   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, Splat0->getOpcode());
62   EXPECT_EQ(Splat0->getOperand(1).getReg(), Splat0->getOperand(2).getReg());
63   EXPECT_EQ(&*MIBCst, MRI->getVRegDef(Splat0->getOperand(1).getReg()));
64 
65   auto FSplat = CSEB.buildFConstant(LLT::vector(2, s32), 1.0);
66   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, FSplat->getOpcode());
67   EXPECT_EQ(FSplat->getOperand(1).getReg(), FSplat->getOperand(2).getReg());
68   EXPECT_EQ(&*MIBFP0, MRI->getVRegDef(FSplat->getOperand(1).getReg()));
69 
70   // Check G_UNMERGE_VALUES
71   auto MIBUnmerge = CSEB.buildUnmerge({s32, s32}, Copies[0]);
72   auto MIBUnmerge2 = CSEB.buildUnmerge({s32, s32}, Copies[0]);
73   EXPECT_TRUE(&*MIBUnmerge == &*MIBUnmerge2);
74 }
75 
76 TEST_F(GISelMITest, TestCSEConstantConfig) {
77   if (!TM)
78     return;
79 
80   LLT s16{LLT::scalar(16)};
81   auto MIBInput = B.buildInstr(TargetOpcode::G_TRUNC, {s16}, {Copies[0]});
82   auto MIBAdd = B.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
83   auto MIBZero = B.buildConstant(s16, 0);
84   GISelCSEInfo CSEInfo;
85   CSEInfo.setCSEConfig(make_unique<CSEConfigConstantOnly>());
86   CSEInfo.analyze(*MF);
87   B.setCSEInfo(&CSEInfo);
88   CSEMIRBuilder CSEB(B.getState());
89   CSEB.setInsertPt(*EntryMBB, EntryMBB->begin());
90   auto MIBAdd1 =
91       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
92   // We should CSE constants only. Adds should not be CSEd.
93   EXPECT_TRUE(MIBAdd1->getOpcode() != TargetOpcode::COPY);
94   EXPECT_TRUE(&*MIBAdd1 != &*MIBAdd);
95   // We should CSE constant.
96   auto MIBZeroTmp = CSEB.buildConstant(s16, 0);
97   EXPECT_TRUE(&*MIBZero == &*MIBZeroTmp);
98 }
99 } // namespace
100