在LLVM IR中调用x86 MMX内置函数

3

我该如何在LLVM中调用MMX内部函数?这段代码导致断言失败,因为内部函数的参数类型不正确。然而,我无法猜测出正确的类型。 最有可能的假设是类似于“MMX向量”的东西。但我还没有找到处理这些类型的适当代码片段。

Value* IRGenContext::emitSaturatingSubUI8(Value* lho, Value* rho, const Twine& name)
{
  Type* mmxType = Type::getX86_MMXTy(session_.lctx());
  std::vector<Type*> paramTypes = { mmxType, mmxType };
  std::vector<Value*> paramVals = { 
    irBuilder().CreateCast(llvm::Instruction::CastOps::BitCast, lho, mmxType),
    irBuilder().CreateCast(llvm::Instruction::CastOps::BitCast, rho, mmxType)
  };
  Function* subsIntr = getIntrinsic(llvm::Intrinsic::x86_mmx_psubs_b, paramTypes);
  Value* intrinsicResult = irBuilder().CreateCall(subsIntr, paramVals, name);
  return irBuilder().CreateCast(llvm::Instruction::CastOps::BitCast, intrinsicResult, getUOctaTy());
}

Function* IRGenContext::getIntrinsic(llvm::Intrinsic::ID id, llvm::ArrayRef<llvm::Type*> Tys)
{
  return llvm::Intrinsic::getDeclaration(module_.get(), id, Tys);
}

它的表示如下所示:

它导致了断言错误:

断言失败:DAG.getTargetLoweringInfo().isTypeLegal(PartVT) && "Copying to an illegal type!", file F:\cpp\llvm-git\llvm\lib\CodeGen\SelectionDAG\SelectionDAGBuilder.cpp, line 376

; ModuleID = 'jit_module_560'                                                   
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"                     

define void @jit_fn559(i8* %cookie) {                                           
Block_6010:                                                                     
  %0 = call i64 @_readRegUint(i8* %cookie, i8 2)                                
  %1 = call i64 @_readRegUint(i8* %cookie, i8 3)                                
  %2 = call i64 @_readRegUint(i8* %cookie, i8 4)                                
  br label %Block_6010.split                                                    

Block_6010.split:                                 ; preds = %Block_6010         
  %reg561 = phi i64 [ 0, %Block_6010 ]                                          
  %reg562 = phi i64 [ %0, %Block_6010 ]                                         
  %reg563 = phi i64 [ %1, %Block_6010 ]                                         
  %reg564 = phi i64 [ %2, %Block_6010 ]                                         
  %"#c1010100" = or i64 %reg561, 0                                              
  %"#c1020200" = or i64 %reg562, 0                                              
  %"#c1030300" = or i64 %reg563, 0                                              
  %"#c1040400" = or i64 %reg564, 0                                              
  %3 = bitcast i64 %"#c1020200" to x86_mmx                                      
  %4 = bitcast i64 %"#c1030300" to x86_mmx                                      
  %5 = call x86_mmx @llvm.x86.mmx.psubs.b.x86mmx.x86mmx(x86_mmx %3, x86_mmx %4) 
  %6 = bitcast x86_mmx %5 to i64                                                
  call void @_storeMemUint64(i8* %cookie, i64 %"#c1040400", i64 0, i64 %6)      
  %7 = call i64 @_readSpRegUint(i8* %cookie, i8 4)                              
  call void @_pop(i8* %cookie, i64 %7, i8 0)                                    
  ret void                                                                      
}                                                                               

declare i64 @_readRegUint(i8*, i8)                                              

declare void @_storeRegUint(i8*, i8, i64)                                       

declare x86_mmx @llvm.x86.mmx.psubs.b.x86mmx.x86mmx(x86_mmx, x86_mmx)           

declare void @_storeMemUint64(i8*, i64, i64, i64)                               

declare i64 @_readSpRegUint(i8*, i8)                                            

declare void @_pop(i8*, i64, i8)                                                
1个回答

3
你可以在位于llvm/include/llvm/IR/的Intrinsics TableGen文件中查找Intrinsic所需的类型。

来自IntrinsicsX86.td

  3583   def int_x86_mmx_psub_b : GCCBuiltin<"__builtin_ia32_psubb">,
  3584               Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty],
  3585                         [IntrNoMem]>;

在您的情况下,您需要使用 x86mmx_ty。为了获得此指令的正确类型,您可以向clang询问。

编译调用内置函数以产生带有垃圾值的内部函数:

void foo()
{
  __builtin_ia32_psubb(42, "42"); // we need the error
} 

results in:

test.c:3:24: error: passing 'int' to parameter of incompatible type '__attribute__((__vector_size__(8 * sizeof(char)))) char' (vector of 8 'char' values)
  __builtin_ia32_psubb(42, "42");

因此,这个内在函数的正确类型是“8个字符向量”。

由于该内在函数没有类型重载,您不应调用它。

Function* subsIntr = getIntrinsic(llvm::Intrinsic::x86_mmx_psubs_b, paramTypes);

带有参数类型:

Function* subsIntr = getIntrinsic(llvm::Intrinsic::x86_mmx_psubs_b);

对于你的目的来说,这是完全可以的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接