Lowering intrinsics / type promotion


I'm not sure how to handle intrinsic functions that have non-i32 operands. The target only supports 32-bit registers natively but for some operations, only the lower 16 bits are significant.

For example, the SMULS instruction does a 16 x 16 fractional multiply with saturation. I've defined an intrinsic function:

int __builtin_opus_smuls(short a, short b);

def int_opus_smuls : GCCBuiltin<"__builtin_opus_smuls">,
Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty],

; ModuleID = 'test.c'
target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-n32"
target triple = "opus-octasic-unknownos"

@a = common global i16 0, align 2
@b = common global i16 0, align 2

define i32 @main() #0 {
  %retval = alloca i32, align 4
  store i32 0, i32* %retval
  %0 = load i16* @a, align 4
  %1 = load i16* @b, align 2
  %2 = call i32 @llvm.opus.smuls(i16 %0, i16 %1)
  ret i32 %2

declare i32 @llvm.opus.smuls(i16, i16) #1

PromoteIntegerOperand Op #1: 0x33f090: i32 = llvm.opus.smuls 0x33f008, 0x33ee70, 0x33ef80 [ORD=4] [ID=0]

Do not know how to promote this operator's operand!
UNREACHABLE executed at ..\..\..\..\lib\CodeGen\SelectionDAG\LegalizeIntegerTypes.cpp:763!

I've tried adding a custom LowerINTRINSIC_WO_CHAIN handler. What's the right way of doing this?