================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits