diff --git a/cranelift/codegen/meta/src/shared/legalize.rs b/cranelift/codegen/meta/src/shared/legalize.rs index 05ffc99dfb..2f20e5a613 100644 --- a/cranelift/codegen/meta/src/shared/legalize.rs +++ b/cranelift/codegen/meta/src/shared/legalize.rs @@ -275,6 +275,17 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro ], ); + narrow.legalize( + def!(a = popcnt.I128(x)), + vec![ + def!((xl, xh) = isplit(x)), + def!(e1 = popcnt(xl)), + def!(e2 = popcnt(xh)), + def!(e3 = iadd(e1, e2)), + def!(a = uextend(e3)), + ], + ); + // TODO(ryzokuken): benchmark this and decide if branching is a faster // approach than evaluating boolean expressions. diff --git a/cranelift/filetests/filetests/legalizer/popcnt-i128.clif b/cranelift/filetests/filetests/legalizer/popcnt-i128.clif new file mode 100644 index 0000000000..b241c640a9 --- /dev/null +++ b/cranelift/filetests/filetests/legalizer/popcnt-i128.clif @@ -0,0 +1,31 @@ +test legalizer +target i686 + +function %foo() -> i128 { +ebb0: + v1 = iconst.i64 0x6400000042 + v2 = iconst.i64 0x7F10100042 + v3 = iconcat v1, v2 + v4 = popcnt.i128 v3 + return v4 +} + +; check: v5 = iconst.i32 66 +; check: v6 = iconst.i32 100 +; check: v1 = iconcat v5, v6 +; check: v7 = iconst.i32 0x1010_0042 +; check: v8 = iconst.i32 127 +; check: v2 = iconcat v7, v8 +; check: v3 = iconcat v1, v2 +; check: v9 = popcnt v1 +; check: v10 = popcnt v2 +; check: v12, v13 = isplit v9 +; check: v14, v15 = isplit v10 +; check: v16, v17 = iadd_ifcout v12, v14 +; check: v18 = iadd_ifcin v13, v15, v17 +; check: v11 = iconcat v16, v18 +; check: v4 = uextend.i128 v11 +; check: v19, v20 = isplit v4 +; check: v21, v22 = isplit v19 +; check: v23, v24 = isplit v20 +; check: return v21, v22, v23, v24