[CodeGen] Support opaque pointers for inline asm

This is the last part of D116531. Fetch the type of the indirect
inline asm operand from the elementtype attribute, rather than
the pointer element type.

Fixes https://github.com/llvm/llvm-project/issues/52928.
This commit is contained in:
Nikita Popov 2022-01-07 10:55:01 +01:00
parent 2cd2600aba
commit 0312fe2901
3 changed files with 30 additions and 16 deletions

View File

@ -8250,7 +8250,8 @@ public:
/// corresponds to. If there is no Value* for this operand, it returns
/// MVT::Other.
EVT getCallOperandValEVT(LLVMContext &Context, const TargetLowering &TLI,
const DataLayout &DL) const {
const DataLayout &DL,
llvm::Type *ParamElemType) const {
if (!CallOperandVal) return MVT::Other;
if (isa<BasicBlock>(CallOperandVal))
@ -8262,10 +8263,8 @@ public:
// If this is an indirect operand, the operand is a pointer to the
// accessed type.
if (isIndirect) {
PointerType *PtrTy = dyn_cast<PointerType>(OpTy);
if (!PtrTy)
report_fatal_error("Indirect operand for inline asm not a pointer!");
OpTy = PtrTy->getElementType();
OpTy = ParamElemType;
assert(OpTy && "Indirect opernad must have elementtype attribute");
}
// Look for vector wrapped in a struct. e.g. { <16 x i8> }.
@ -8566,17 +8565,16 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// Compute the value type for each operand.
if (OpInfo.hasArg()) {
OpInfo.CallOperandVal = Call.getArgOperand(ArgNo++);
OpInfo.CallOperandVal = Call.getArgOperand(ArgNo);
// Process the call argument. BasicBlocks are labels, currently appearing
// only in asm's.
if (isa<CallBrInst>(Call) &&
ArgNo - 1 >= (cast<CallBrInst>(&Call)->arg_size() -
ArgNo >= (cast<CallBrInst>(&Call)->arg_size() -
cast<CallBrInst>(&Call)->getNumIndirectDests() -
NumMatchingOps) &&
(NumMatchingOps == 0 ||
ArgNo - 1 <
(cast<CallBrInst>(&Call)->arg_size() - NumMatchingOps))) {
ArgNo < (cast<CallBrInst>(&Call)->arg_size() - NumMatchingOps))) {
const auto *BA = cast<BlockAddress>(OpInfo.CallOperandVal);
EVT VT = TLI.getValueType(DAG.getDataLayout(), BA->getType(), true);
OpInfo.CallOperand = DAG.getTargetBlockAddress(BA, VT);
@ -8586,9 +8584,11 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
}
Type *ParamElemTy = Call.getAttributes().getParamElementType(ArgNo);
EVT VT = OpInfo.getCallOperandValEVT(*DAG.getContext(), TLI,
DAG.getDataLayout());
DAG.getDataLayout(), ParamElemTy);
OpInfo.ConstraintVT = VT.isSimple() ? VT.getSimpleVT() : MVT::Other;
ArgNo++;
} else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect) {
// The return value of the call is this value. As such, there is no
// corresponding argument.

View File

@ -4751,7 +4751,7 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
case InlineAsm::isOutput:
// Indirect outputs just consume an argument.
if (OpInfo.isIndirect) {
OpInfo.CallOperandVal = Call.getArgOperand(ArgNo++);
OpInfo.CallOperandVal = Call.getArgOperand(ArgNo);
break;
}
@ -4769,7 +4769,7 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
++ResNo;
break;
case InlineAsm::isInput:
OpInfo.CallOperandVal = Call.getArgOperand(ArgNo++);
OpInfo.CallOperandVal = Call.getArgOperand(ArgNo);
break;
case InlineAsm::isClobber:
// Nothing to do.
@ -4779,10 +4779,8 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
if (OpInfo.CallOperandVal) {
llvm::Type *OpTy = OpInfo.CallOperandVal->getType();
if (OpInfo.isIndirect) {
llvm::PointerType *PtrTy = dyn_cast<PointerType>(OpTy);
if (!PtrTy)
report_fatal_error("Indirect operand for inline asm not a pointer!");
OpTy = PtrTy->getElementType();
OpTy = Call.getAttributes().getParamElementType(ArgNo);
assert(OpTy && "Indirect opernad must have elementtype attribute");
}
// Look for vector wrapped in a struct. e.g. { <16 x i8> }.
@ -4812,6 +4810,8 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
} else {
OpInfo.ConstraintVT = MVT::getVT(OpTy, true);
}
ArgNo++;
}
}

View File

@ -0,0 +1,14 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-linux -opaque-pointers < %s | FileCheck %s
define void @okay(ptr %p, i32 %x) nounwind {
; CHECK-LABEL: okay:
; CHECK: # %bb.0:
; CHECK-NEXT: #APP
; CHECK-NEXT: addl %esi, %eax
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: movl %eax, (%rdi)
; CHECK-NEXT: retq
call void asm "addl $1, $0", "=*r,r"(ptr elementtype(i32) %p, i32 %x)
ret void
}