PreLowerPeeps.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "BackEnd.h"
  6. IR::Instr *Lowerer::PreLowerPeepInstr(IR::Instr *instr, IR::Instr **pInstrPrev)
  7. {
  8. if (!PHASE_ON(Js::PreLowererPeepsPhase, this->m_func))
  9. {
  10. return instr;
  11. }
  12. switch (instr->m_opcode)
  13. {
  14. case Js::OpCode::Shl_I4:
  15. instr = this->PeepShl(instr);
  16. *pInstrPrev = instr->m_prev;
  17. break;
  18. case Js::OpCode::BrTrue_I4:
  19. case Js::OpCode::BrFalse_I4:
  20. instr = this->PeepBrBool(instr);
  21. *pInstrPrev = instr->m_prev;
  22. break;
  23. }
  24. return instr;
  25. }
  26. IR::Instr *Lowerer::PeepShl(IR::Instr *instrShl)
  27. {
  28. IR::Opnd *src1;
  29. IR::Opnd *src2;
  30. IR::Instr *instrDef;
  31. src1 = instrShl->GetSrc1();
  32. src2 = instrShl->GetSrc2();
  33. // Peep:
  34. // t1 = SHR X, cst
  35. // t2 = SHL t1, cst
  36. //
  37. // Into:
  38. // t2 = AND X, mask
  39. if (!src1->IsRegOpnd() || !src2->IsIntConstOpnd())
  40. {
  41. return instrShl;
  42. }
  43. if (!src1->AsRegOpnd()->m_sym->IsSingleDef())
  44. {
  45. return instrShl;
  46. }
  47. if (instrShl->HasBailOutInfo())
  48. {
  49. return instrShl;
  50. }
  51. instrDef = src1->AsRegOpnd()->m_sym->GetInstrDef();
  52. if (instrDef->m_opcode != Js::OpCode::Shr_I4 || !instrDef->GetSrc2()->IsIntConstOpnd()
  53. || instrDef->GetSrc2()->AsIntConstOpnd()->GetValue() != src2->AsIntConstOpnd()->GetValue()
  54. || !instrDef->GetSrc1()->IsRegOpnd())
  55. {
  56. return instrShl;
  57. }
  58. if (!src1->GetIsDead())
  59. {
  60. return instrShl;
  61. }
  62. if (instrDef->HasBailOutInfo())
  63. {
  64. return instrShl;
  65. }
  66. if (IR::Instr::FindRegUseInRange(src1->AsRegOpnd()->m_sym, instrDef->m_next, instrShl->m_prev))
  67. {
  68. return instrShl;
  69. }
  70. FOREACH_INSTR_IN_RANGE(instrIter, instrDef->m_next, instrShl->m_prev)
  71. {
  72. if (instrIter->HasBailOutInfo())
  73. {
  74. return instrShl;
  75. }
  76. if (instrIter->FindRegDef(instrDef->GetSrc1()->AsRegOpnd()->m_sym))
  77. {
  78. return instrShl;
  79. }
  80. if (instrIter->FindRegUse(src1->AsRegOpnd()->m_sym))
  81. {
  82. return instrShl;
  83. }
  84. } NEXT_INSTR_IN_RANGE;
  85. instrShl->FreeSrc1();
  86. instrShl->SetSrc1(instrDef->UnlinkSrc1());
  87. instrDef->Remove();
  88. IntConstType oldValue = src2->AsIntConstOpnd()->GetValue();
  89. oldValue = ~((1 << oldValue) - 1);
  90. src2->AsIntConstOpnd()->SetValue(oldValue);
  91. instrShl->m_opcode = Js::OpCode::And_I4;
  92. return instrShl;
  93. }
  94. IR::Instr *Lowerer::PeepBrBool(IR::Instr *instrBr)
  95. {
  96. IR::Opnd *src1;
  97. IR::Instr *instrBinOp, *instrCm1, *instrCm2;
  98. // Peep:
  99. // t1 = CmCC_I4 a, b
  100. // t2 = CmCC_i4 c, d
  101. // t3 = AND/OR t1, t2
  102. // BrTrue/False t3, $L_true
  103. //
  104. // Into:
  105. // BrCC a, b, $L_true/false
  106. // BrCC c, d, $L_true
  107. //$L_false:
  108. src1 = instrBr->GetSrc1();
  109. if (!src1->IsRegOpnd())
  110. {
  111. return instrBr;
  112. }
  113. Assert(!instrBr->HasBailOutInfo());
  114. instrBinOp = instrBr->GetPrevRealInstrOrLabel();
  115. if (instrBinOp->m_opcode != Js::OpCode::And_I4 && instrBinOp->m_opcode != Js::OpCode::Or_I4)
  116. {
  117. return instrBr;
  118. }
  119. if (!instrBinOp->GetDst()->IsEqual(src1))
  120. {
  121. return instrBr;
  122. }
  123. IR::RegOpnd *src1Reg = src1->AsRegOpnd();
  124. if (!src1Reg->m_sym->IsSingleDef() || !src1Reg->GetIsDead())
  125. {
  126. return instrBr;
  127. }
  128. Assert(!instrBinOp->HasBailOutInfo());
  129. instrCm2 = instrBinOp->GetPrevRealInstrOrLabel();
  130. if (!instrCm2->IsCmCC_I4())
  131. {
  132. return instrBr;
  133. }
  134. IR::RegOpnd *cm2DstReg = instrCm2->GetDst()->AsRegOpnd();
  135. if (!cm2DstReg->m_sym->IsSingleDef())
  136. {
  137. return instrBr;
  138. }
  139. if (cm2DstReg->IsEqual(instrBinOp->GetSrc1()))
  140. {
  141. if (!instrBinOp->GetSrc1()->AsRegOpnd()->GetIsDead())
  142. {
  143. return instrBr;
  144. }
  145. }
  146. else if (cm2DstReg->IsEqual(instrBinOp->GetSrc2()))
  147. {
  148. if (!instrBinOp->GetSrc2()->AsRegOpnd()->GetIsDead())
  149. {
  150. return instrBr;
  151. }
  152. }
  153. else
  154. {
  155. return instrBr;
  156. }
  157. Assert(!instrCm2->HasBailOutInfo());
  158. instrCm1 = instrCm2->GetPrevRealInstrOrLabel();
  159. if (!instrCm1->IsCmCC_I4())
  160. {
  161. return instrBr;
  162. }
  163. Assert(!instrCm1->GetDst()->IsEqual(instrCm2->GetDst()));
  164. IR::RegOpnd *cm1DstReg = instrCm1->GetDst()->AsRegOpnd();
  165. if (!cm1DstReg->m_sym->IsSingleDef())
  166. {
  167. return instrBr;
  168. }
  169. if (cm1DstReg->IsEqual(instrBinOp->GetSrc1()))
  170. {
  171. if (!instrBinOp->GetSrc1()->AsRegOpnd()->GetIsDead())
  172. {
  173. return instrBr;
  174. }
  175. }
  176. else if (cm1DstReg->IsEqual(instrBinOp->GetSrc2()))
  177. {
  178. if (!instrBinOp->GetSrc2()->AsRegOpnd()->GetIsDead())
  179. {
  180. return instrBr;
  181. }
  182. }
  183. else
  184. {
  185. return instrBr;
  186. }
  187. Assert(!instrCm1->HasBailOutInfo());
  188. IR::LabelInstr *falseLabel = instrBr->AsBranchInstr()->GetTarget();
  189. IR::LabelInstr *trueLabel = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
  190. instrBr->InsertAfter(trueLabel);
  191. IR::BranchInstr *instrBr1;
  192. IR::BranchInstr *instrBr2;
  193. if (instrBinOp->m_opcode == Js::OpCode::And_I4)
  194. {
  195. instrBr1 = instrCm1->ChangeCmCCToBranchInstr(instrBr->m_opcode == Js::OpCode::BrFalse_I4 ? falseLabel : trueLabel);
  196. instrBr1->Invert();
  197. instrBr2 = instrCm2->ChangeCmCCToBranchInstr(falseLabel);
  198. if (instrBr->m_opcode == Js::OpCode::BrFalse_I4)
  199. {
  200. instrBr2->Invert();
  201. }
  202. }
  203. else
  204. {
  205. Assert(instrBinOp->m_opcode == Js::OpCode::Or_I4);
  206. instrBr1 = instrCm1->ChangeCmCCToBranchInstr(instrBr->m_opcode == Js::OpCode::BrTrue_I4 ? falseLabel : trueLabel);
  207. instrBr2 = instrCm2->ChangeCmCCToBranchInstr(falseLabel);
  208. if (instrBr->m_opcode == Js::OpCode::BrFalse_I4)
  209. {
  210. instrBr2->Invert();
  211. }
  212. }
  213. instrBinOp->Remove();
  214. instrBr->Remove();
  215. return instrBr2;
  216. }