[clang] [InstCombine] Convert or concat to fshl if opposite or concat exists (PR #68502)

via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 19 23:50:57 PDT 2023


================
@@ -2840,6 +2841,46 @@ static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC) {
       return nullptr;
 
     FShiftArgs = {ShVal0, ShVal1, ShAmt};
+  } else if (isa<ZExtInst>(Or0) || isa<ZExtInst>(Or1)) {
+    // If there are two 'or' instructions concat variables in opposite order,
+    // the latter one can be safely convert to fshl.
+    //
+    // LowHigh = or (shl (zext Low), Width - ZextHighShlAmt), (zext High)
+    // HighLow = or (shl (zext High), ZextHighShlAmt), (zext Low)
+    // ->
+    // HighLow = fshl LowHigh, LowHigh, ZextHighShlAmt
+    if (!isa<ZExtInst>(Or1))
+      std::swap(Or0, Or1);
+
+    Value *High, *ZextHigh, *Low;
+    const APInt *ZextHighShlAmt;
+    if (!match(Or0,
+               m_OneUse(m_Shl(m_Value(ZextHigh), m_APInt(ZextHighShlAmt)))))
+      return nullptr;
+
+    if (!match(Or1, m_ZExt(m_Value(Low))) ||
+        !match(ZextHigh, m_ZExt(m_Value(High))))
----------------
HaohaiWen wrote:

If we only match (shl i32, 8), we can't guarantee it's reverse concat since we don't know if the most significant 8bit in i32 is zero.
```
%zext.x = zext i8 %x to i32 
%slx = shl nuw i32 %zext.x, 24 
%zext.y = zext i24 %y to i32 
%xy = or i32 %zext.y, %slx        #[x[7:0], y[23:0]]
%sly = shl nuw i32 %zext.y, 8 
%yx = or i32 %zext.x, %sly        #[y[23:0], x[7:0]]
```
If not match zext:
```
%zext.x = zext i8 %x to i32 
%slx = shl nuw i32 %zext.x, 24 
%xy = or i32 %y, %slx              #[unknown, y[23,0]]             y[31:24] may not be zero.
%sly = shl nuw i32 %y, 8           #[y[23:0], 0,0,0,0,0,0,0,0]
%yx = or i32 %zext.x, %sly         #[y[23:0], x[7:0]]
```



https://github.com/llvm/llvm-project/pull/68502


More information about the cfe-commits mailing list