{"record":{"id":"eb987ab276c17653","repo":"jax-ml/jax","slug":"can-t-bitcast-x-type-of-bitwidth-x-bw-to-ne","errorCode":null,"errorMessage":"Can't bitcast {x.type} (of bitwidth {x_bw}) to {new_type} (of bitwidth {new_bw})","messagePattern":"Can't bitcast (.+?) \\(of bitwidth (.+?)\\) to (.+?) \\(of bitwidth (.+?)\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/experimental/mosaic/gpu/utils.py","lineNumber":2066,"sourceCode":"    raise ValueError(f\"Types must match, got {high.type} and {low.type}\")\n  if high.type != i32:\n    high = bitcast(high, i32)\n  if low.type != i32:\n    low = bitcast(low, i32)\n  if permutation.type != i32:\n    permutation = bitcast(permutation, i32)\n  result = llvm.inline_asm(\n      i32, [high, low, permutation], \"prmt.b32 $0, $1, $2, $3;\", \"=r,r,r,r\"\n  )\n  assert isinstance(result, ir.Value)\n  return bitcast(result, result_type)\n\n\ndef bitcast(x: ir.Value, new_type: ir.Type):\n  if x.type == new_type:\n    return x\n  if (x_bw := bitwidth(x.type)) != (new_bw := bitwidth(new_type)):\n    raise ValueError(\n        f\"Can't bitcast {x.type} (of bitwidth {x_bw}) to {new_type} (of\"\n        f\" bitwidth {new_bw})\"\n    )\n  if isinstance(x.type, ir.VectorType) and isinstance(new_type, ir.IntegerType):\n    new_type = ir.IntegerType(new_type)\n    x_ty = ir.VectorType(x.type)\n    assert new_type.width == bitwidth(x_ty.element_type) * math.prod(x_ty.shape)\n    return vector.extract(\n        vector.bitcast(ir.VectorType.get((1,), new_type), x),\n        dynamic_position=[],\n        static_position=ir.DenseI64ArrayAttr.get([0]),\n    )\n  if isinstance(x.type, ir.IntegerType) and isinstance(new_type, ir.VectorType):\n    new_type = ir.VectorType(new_type)\n    x_ty = ir.IntegerType(x.type)\n    assert x_ty.width == bitwidth(new_type.element_type) * math.prod(\n        new_type.shape\n    )","sourceCodeStart":2048,"sourceCodeEnd":2084,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/experimental/mosaic/gpu/utils.py#L2048-L2084","documentation":"bitcast only reinterprets bits, so the total bitwidth must be preserved. This check compares the source bitwidth (including whole vectors) to the target's; a size change cannot be a bitcast and must go through a cast/extension/truncation op instead.","triggerScenarios":"Calling bitcast(x, new_type) where bitwidths differ, e.g. bitcasting vector<4xf32> (128 bits) to i64 (64 bits), or f32 to i8.","commonSituations":"Assuming bitcast can widen/narrow like reinterpret-with-resize; converting bf16x2 packing by bitcasting vector<2xbf16> to f32 (works) but to f16 (fails); mixing up truncation with reinterpreting.","solutions":["Use a real cast: arith.trunci/extsi/extui for integers, arith.extf/truncf for floats","If packing/unpacking vectors, make the total bitwidth match exactly (e.g. vector<2xbf16> <-> i32)","For unequal widths, first cast to the same width then bitcast"],"exampleFix":"# before\nx_i8 = bitcast(x_f32, ir.IntegerType.get_signless(8))  # 32 -> 8 bits\n# after\nx_i32 = bitcast(x_f32, ir.IntegerType.get_signless(32))\nx_i8 = arith.trunci(ir.IntegerType.get_signless(8), x_i32)","handlingStrategy":"type-guard","validationCode":"assert bitwidth(x.type) == bitwidth(new_type), 'bitcast must preserve total bitwidth'","typeGuard":"def can_bitcast(src_ty, dst_ty) -> bool:\n    return bitwidth(src_ty) == bitwidth(dst_ty)","tryCatchPattern":null,"preventionTips":["Use arith casts for width changes; reserve bitcast for same-width reinterprets","Compute target element counts from bitwidth math when packing"],"tags":["mosaic-gpu","bitcast","bitwidth"],"backgroundTag":"bitwidth-mismatch","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}