genCall (PrimTarget (MO_U_QuotRem2 w))
        [dstQ, dstR] [lhsH, lhsL, rhs] = runStmtsDecls $ do
    let width = widthToLlvmInt w
        bitWidth = widthInBits w
        width2x = LMInt (bitWidth * 2)
    -- First zero-extend all parameters to double width.
    let zeroExtend expr = do
            var <- exprToVarW expr
            doExprW width2x $ Cast LM_Zext var width2x
    lhsExtH <- zeroExtend lhsH
    lhsExtL <- zeroExtend lhsL
    rhsExt <- zeroExtend rhs
    -- Now we combine the first two parameters (that represent the high and low
    -- bits of the value). So first left-shift the high bits to their position
    -- and then bit-or them with the low bits.
    let widthLlvmLit = LMLitVar $ LMIntLit (fromIntegral bitWidth) width
    lhsExtHShifted <- doExprW width2x $ LlvmOp LM_MO_Shl lhsExtH widthLlvmLit
    lhsExt <- doExprW width2x $ LlvmOp LM_MO_Or lhsExtHShifted lhsExtL
    -- Finally, we can call 'udiv' and 'urem' to compute the results.
    retExtDiv <- doExprW width2x $ LlvmOp LM_MO_UDiv lhsExt rhsExt
    retExtRem <- doExprW width2x $ LlvmOp LM_MO_URem lhsExt rhsExt
    -- And since everything is in 2x width, we need to truncate the results and
    -- then return them.
    let narrow var = doExprW width $ Cast LM_Trunc var width
    retDiv <- narrow retExtDiv
    retRem <- narrow retExtRem
    dstRegQ <- lift $ getCmmReg (CmmLocal dstQ)
    dstRegR <- lift $ getCmmReg (CmmLocal dstR)
    statement $ Store retDiv dstRegQ
    statement $ Store retRem dstRegR

-- Handle the MO_{Add,Sub}IntC separately. LLVM versions return a record from
-- which we need to extract the actual values.
genCall (PrimTarget (MO_U_QuotRem2 w))
        [dstQ, dstR] [lhsH, lhsL, rhs] = runStmtsDecls $ do
    let width = widthToLlvmInt w
        bitWidth = widthInBits w
        width2x = LMInt (bitWidth * 2)
    -- First zero-extend all parameters to double width.
    let zeroExtend expr = do
            var <- exprToVarW expr
            doExprW width2x $ Cast LM_Zext var width2x
    lhsExtH <- zeroExtend lhsH
    lhsExtL <- zeroExtend lhsL
    rhsExt <- zeroExtend rhs
    -- Now we combine the first two parameters (that represent the high and low
    -- bits of the value). So first left-shift the high bits to their position
    -- and then bit-or them with the low bits.
    let widthLlvmLit = LMLitVar $ LMIntLit (fromIntegral bitWidth) width
    lhsExtHShifted <- doExprW width2x $ LlvmOp LM_MO_Shl lhsExtH widthLlvmLit
    lhsExt <- doExprW width2x $ LlvmOp LM_MO_Or lhsExtHShifted lhsExtL
    -- Finally, we can call 'udiv' and 'urem' to compute the results.
    retExtDiv <- doExprW width2x $ LlvmOp LM_MO_UDiv lhsExt rhsExt
    retExtRem <- doExprW width2x $ LlvmOp LM_MO_URem lhsExt rhsExt
    -- And since everything is in 2x width, we need to truncate the results and
    -- then return them.
    let narrow var = doExprW width $ Cast LM_Trunc var width
    retDiv <- narrow retExtDiv
    retRem <- narrow retExtRem
    dstRegQ <- lift $ getCmmReg (CmmLocal dstQ)
    dstRegR <- lift $ getCmmReg (CmmLocal dstR)
    statement $ Store retDiv dstRegQ
    statement $ Store retRem dstRegR

-- Handle the MO_{Add,Sub}IntC separately. LLVM versions return a record from
-- which we need to extract the actual values.
genCall (PrimTarget (MO_U_QuotRem2 w))
        [dstQ, dstR] [lhsH, lhsL, rhs] = runStmtsDecls $ do
    let width = widthToLlvmInt w
        bitWidth = widthInBits w
        width2x = LMInt (bitWidth * 2)
    -- First zero-extend all parameters to double width.
    let zeroExtend expr = do
            var <- exprToVarW expr
            doExprW width2x $ Cast LM_Zext var width2x
    lhsExtH <- zeroExtend lhsH
    lhsExtL <- zeroExtend lhsL
    rhsExt <- zeroExtend rhs
    -- Now we combine the first two parameters (that represent the high and low
    -- bits of the value). So first left-shift the high bits to their position
    -- and then bit-or them with the low bits.
    let widthLlvmLit = LMLitVar $ LMIntLit (fromIntegral bitWidth) width
    lhsExtHShifted <- doExprW width2x $ LlvmOp LM_MO_Shl lhsExtH widthLlvmLit
    lhsExt <- doExprW width2x $ LlvmOp LM_MO_Or lhsExtHShifted lhsExtL
    -- Finally, we can call 'udiv' and 'urem' to compute the results.
    retExtDiv <- doExprW width2x $ LlvmOp LM_MO_UDiv lhsExt rhsExt
    retExtRem <- doExprW width2x $ LlvmOp LM_MO_URem lhsExt rhsExt
    -- And since everything is in 2x width, we need to truncate the results and
    -- then return them.
    let narrow var = doExprW width $ Cast LM_Trunc var width
    retDiv <- narrow retExtDiv
    retRem <- narrow retExtRem
    dstRegQ <- lift $ getCmmReg (CmmLocal dstQ)
    dstRegR <- lift $ getCmmReg (CmmLocal dstR)
    statement $ Store retDiv dstRegQ
    statement $ Store retRem dstRegR

-- Handle the MO_{Add,Sub}IntC separately. LLVM versions return a record from
-- which we need to extract the actual values.