diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -482,7 +482,6 @@ this->FTy = FTy; assert(getNumOperands() == Args.size() + CountBundleInputs(Bundles) + 1 && "NumOperands not set up?"); - setCalledOperand(Func); #ifndef NDEBUG assert((Args.size() == FTy->getNumParams() || @@ -495,7 +494,10 @@ "Calling a function with a bad signature!"); #endif + // Set operands in order of their index to match use-list-order + // prediction. llvm::copy(Args, op_begin()); + setCalledOperand(Func); auto It = populateBundleOperandInfos(Bundles, Args.size()); (void)It; @@ -824,9 +826,6 @@ assert((int)getNumOperands() == ComputeNumOperands(Args.size(), CountBundleInputs(Bundles)) && "NumOperands not set up?"); - setNormalDest(IfNormal); - setUnwindDest(IfException); - setCalledOperand(Fn); #ifndef NDEBUG assert(((Args.size() == FTy->getNumParams()) || @@ -839,7 +838,12 @@ "Invoking a function with a bad signature!"); #endif + // Set operands in order of their index to match use-list-order + // prediction. llvm::copy(Args, op_begin()); + setNormalDest(IfNormal); + setUnwindDest(IfException); + setCalledOperand(Fn); auto It = populateBundleOperandInfos(Bundles, Args.size()); (void)It; @@ -892,11 +896,6 @@ ComputeNumOperands(Args.size(), IndirectDests.size(), CountBundleInputs(Bundles)) && "NumOperands not set up?"); - NumIndirectDests = IndirectDests.size(); - setDefaultDest(Fallthrough); - for (unsigned i = 0; i != NumIndirectDests; ++i) - setIndirectDest(i, IndirectDests[i]); - setCalledOperand(Fn); #ifndef NDEBUG assert(((Args.size() == FTy->getNumParams()) || @@ -909,7 +908,14 @@ "Calling a function with a bad signature!"); #endif + // Set operands in order of their index to match use-list-order + // prediction. std::copy(Args.begin(), Args.end(), op_begin()); + NumIndirectDests = IndirectDests.size(); + setDefaultDest(Fallthrough); + for (unsigned i = 0; i != NumIndirectDests; ++i) + setIndirectDest(i, IndirectDests[i]); + setCalledOperand(Fn); auto It = populateBundleOperandInfos(Bundles, Args.size()); (void)It; diff --git a/llvm/test/Assembler/call-arg-is-callee.ll b/llvm/test/Assembler/call-arg-is-callee.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Assembler/call-arg-is-callee.ll @@ -0,0 +1,39 @@ +; RUN: llvm-as < %s -disable-output 2>&1 | FileCheck %s -allow-empty +; CHECK-NOT: error +; CHECK-NOT: warning +; RUN: verify-uselistorder < %s + +; Check ordering of callee operand versus the argument operand. +define void @call(void (...)* %p) { + call void (...) %p(void (...)* %p) + ret void +} + +; Check ordering of callee operand versus the argument operand. +declare void @personality(i8*) +define void @invoke(void (...)* %p) personality void(i8*)* @personality { +entry: + invoke void (...) %p(void (...)* %p) + to label %normal unwind label %exception +normal: + ret void +exception: + landingpad { i8*, i32 } cleanup + ret void +} + +; Check order for callbr instruction. Cannot reuse labels in the test since the +; verifier prevents duplicating callbr destinations. +define void @callbr() { +entry: + callbr i32 asm "", "=r,r,X,X"(i32 0, + i8 *blockaddress(@callbr, %two), + i8 *blockaddress(@callbr, %three)) + to label %one [label %two, label %three] +one: + ret void +two: + ret void +three: + ret void +}