LLVM: lib/Target/Mips/MipsAnalyzeImmediate.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

12#include

13#include

14#include

15

16using namespace llvm;

17

19

20

21void MipsAnalyzeImmediate::AddInstr(InstSeqLs &SeqLs, const Inst &I) {

22

23 if (SeqLs.empty()) {

25 return;

26 }

27

28 for (auto &S : SeqLs)

29 S.push_back(I);

30}

31

32void MipsAnalyzeImmediate::GetInstSeqLsADDiu(uint64_t Imm, unsigned RemSize,

33 InstSeqLs &SeqLs) {

34 GetInstSeqLs((Imm + 0x8000ULL) & 0xffffffffffff0000ULL, RemSize, SeqLs);

35 AddInstr(SeqLs, Inst(ADDiu, Imm & 0xffffULL));

36}

37

38void MipsAnalyzeImmediate::GetInstSeqLsORi(uint64_t Imm, unsigned RemSize,

39 InstSeqLs &SeqLs) {

40 GetInstSeqLs(Imm & 0xffffffffffff0000ULL, RemSize, SeqLs);

41 AddInstr(SeqLs, Inst(ORi, Imm & 0xffffULL));

42}

43

44void MipsAnalyzeImmediate::GetInstSeqLsSLL(uint64_t Imm, unsigned RemSize,

45 InstSeqLs &SeqLs) {

47 GetInstSeqLs(Imm >> Shamt, RemSize - Shamt, SeqLs);

48 AddInstr(SeqLs, Inst(SLL, Shamt));

49}

50

51void MipsAnalyzeImmediate::GetInstSeqLs(uint64_t Imm, unsigned RemSize,

52 InstSeqLs &SeqLs) {

53 uint64_t MaskedImm = Imm & (0xffffffffffffffffULL >> (64 - Size));

54

55

56 if (!MaskedImm)

57 return;

58

59

60 if (RemSize <= 16) {

61 AddInstr(SeqLs, Inst(ADDiu, MaskedImm));

62 return;

63 }

64

65

66 if (!(Imm & 0xffff)) {

67 GetInstSeqLsSLL(Imm, RemSize, SeqLs);

68 return;

69 }

70

71 GetInstSeqLsADDiu(Imm, RemSize, SeqLs);

72

73

74

75 if (Imm & 0x8000) {

76 InstSeqLs SeqLsORi;

77 GetInstSeqLsORi(Imm, RemSize, SeqLsORi);

78 SeqLs.append(std::make_move_iterator(SeqLsORi.begin()),

79 std::make_move_iterator(SeqLsORi.end()));

80 }

81}

82

83

84

85

86

87

88

89void MipsAnalyzeImmediate::ReplaceADDiuSLLWithLUi(InstSeq &Seq) {

90

91

92 if ((Seq.size() < 2) || (Seq[0].Opc != ADDiu) ||

93 (Seq[1].Opc != SLL) || (Seq[1].ImmOpnd < 16))

94 return;

95

96

98 int64_t ShiftedImm = (uint64_t)Imm << (Seq[1].ImmOpnd - 16);

99

101 return;

102

103

104 Seq[0].Opc = LUi;

105 Seq[0].ImmOpnd = (unsigned)(ShiftedImm & 0xffff);

106 Seq.erase(Seq.begin() + 1);

107}

108

109void MipsAnalyzeImmediate::GetShortestSeq(InstSeqLs &SeqLs, InstSeq &Insts) {

111

112 unsigned ShortestLength = 8;

113

115 ReplaceADDiuSLLWithLUi(*S);

116 assert(S->size() <= 7);

117

118 if (S->size() < ShortestLength) {

119 ShortestSeq = S;

120 ShortestLength = S->size();

121 }

122 }

123

124 Insts.clear();

125 Insts.append(ShortestSeq->begin(), ShortestSeq->end());

126}

127

130 bool LastInstrIsADDiu) {

131 this->Size = Size;

132

133 if (Size == 32) {

134 ADDiu = Mips::ADDiu;

135 ORi = Mips::ORi;

136 SLL = Mips::SLL;

137 LUi = Mips::LUi;

138 } else {

139 ADDiu = Mips::DADDiu;

140 ORi = Mips::ORi64;

141 SLL = Mips::DSLL;

142 LUi = Mips::LUi64;

143 }

144

145 InstSeqLs SeqLs;

146

147

148 if (LastInstrIsADDiu | !Imm)

149 GetInstSeqLsADDiu(Imm, Size, SeqLs);

150 else

151 GetInstSeqLs(Imm, Size, SeqLs);

152

153

154 GetShortestSeq(SeqLs, Insts);

155

156 return Insts;

157}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

void push_back(const T &Elt)

This is an optimization pass for GlobalISel generic memory operations.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

int countr_zero(T Val)

Count number of 0's from the least significant bit to the most stopping at the first 1.

constexpr int64_t SignExtend64(uint64_t x)

Sign-extend the number in the bottom B bits of X to a 64-bit integer.