forked from OSchip/llvm-project
LLVM IR Dialect: unify call and call0 operations
When the LLVM IR dialect was implemented, TableGen operation definition scheme did not support operations with variadic results. Therefore, the `call` instruction was split into `call` and `call0` for the single- and zero-result calls (LLVM does not support multi-result operations). Unify `call` and `call0` using the recently added TableGen support for operations with Variadic results. Explicitly verify that the new operation has 0 or 1 results. As a side effect, this change enables clean-ups in the conversion to the LLVM IR dialect that no longer needs to rely on wrapped LLVM IR void types when constructing zero-result calls. PiperOrigin-RevId: 236119197
This commit is contained in:
parent
d9cc3c31cc
commit
8cc50208a6
|
@ -39,15 +39,12 @@ def LLVM_Type : Type<CPred<"{0}.isa<::mlir::LLVM::LLVMType>()">,
|
|||
class LLVM_Op<string mnemonic, list<OpTrait> traits = []> :
|
||||
Op<!strconcat("llvm.", mnemonic), traits>;
|
||||
|
||||
// Base class for LLVM operations with one result.
|
||||
class LLVM_OneResultOp<string mnemonic, list<OpTrait> traits = []> :
|
||||
LLVM_Op<mnemonic, traits>, Results<(outs LLVM_Type)> {
|
||||
let builder = [{
|
||||
static void build(Builder *builder, OperationState *result, Type resultType,
|
||||
ArrayRef<Value *> operands,
|
||||
ArrayRef<NamedAttribute> attributes = {}) {
|
||||
(void) builder;
|
||||
result->addTypes(resultType);
|
||||
def LLVM_OneResultOpBuilder {
|
||||
code builder = [{
|
||||
static void build(Builder *, OperationState *result,
|
||||
Type resultType, ArrayRef<Value *> operands,
|
||||
ArrayRef<NamedAttribute> attributes = {}) {
|
||||
if (resultType) result->addTypes(resultType);
|
||||
result->addOperands(operands);
|
||||
for (auto namedAttr : attributes) {
|
||||
result->addAttribute(namedAttr.first, namedAttr.second);
|
||||
|
@ -56,10 +53,33 @@ class LLVM_OneResultOp<string mnemonic, list<OpTrait> traits = []> :
|
|||
}];
|
||||
}
|
||||
|
||||
def LLVM_ZeroResultOpBuilder {
|
||||
code builder = [{
|
||||
static void build(Builder *, OperationState *result,
|
||||
ArrayRef<Value *> operands,
|
||||
ArrayRef<NamedAttribute> attributes = {}) {
|
||||
result->addOperands(operands);
|
||||
for (auto namedAttr : attributes) {
|
||||
result->addAttribute(namedAttr.first, namedAttr.second);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
class LLVM_TwoBuilders<code b1, code b2> {
|
||||
code builder = !cast<code>(!strconcat(!cast<string>(b1), !cast<string>(b2)));
|
||||
}
|
||||
|
||||
// Base class for LLVM operations with one result.
|
||||
class LLVM_OneResultOp<string mnemonic, list<OpTrait> traits = []> :
|
||||
LLVM_Op<mnemonic, traits>, Results<(outs LLVM_Type)> {
|
||||
let builder = LLVM_OneResultOpBuilder.builder;
|
||||
}
|
||||
|
||||
// Base class for LLVM operations with zero results.
|
||||
class LLVM_ZeroResultOp<string mnemonic, list<OpTrait> traits = []> :
|
||||
LLVM_Op<mnemonic, traits>, Results<(outs)> {
|
||||
let builder = [{
|
||||
let builder = LLVM_TwoBuilders<[{
|
||||
// Compatibility builder that takes an instance of wrapped llvm::VoidType
|
||||
// to indicate no result.
|
||||
static void build(Builder *builder, OperationState *result, Type resultType,
|
||||
|
@ -72,18 +92,8 @@ class LLVM_ZeroResultOp<string mnemonic, list<OpTrait> traits = []> :
|
|||
"for zero-result operands, only 'void' is accepted as result type");
|
||||
build(builder, result, operands, attributes);
|
||||
}
|
||||
|
||||
// Convenience builder that does not take a return type.
|
||||
static void build(Builder *builder, OperationState *result,
|
||||
ArrayRef<Value *> operands,
|
||||
ArrayRef<NamedAttribute> attributes = {}) {
|
||||
(void) builder;
|
||||
result->addOperands(operands);
|
||||
for (auto namedAttr : attributes) {
|
||||
result->addAttribute(namedAttr.first, namedAttr.second);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}],
|
||||
LLVM_ZeroResultOpBuilder.builder>.builder;
|
||||
}
|
||||
|
||||
// Base class for LLVM terminator operations. All terminator operations have
|
||||
|
@ -149,10 +159,21 @@ def LLVM_StoreOp : LLVM_ZeroResultOp<"store">,
|
|||
def LLVM_BitcastOp : LLVM_OneResultOp<"bitcast", [NoSideEffect]>,
|
||||
Arguments<(ins LLVM_Type)>;
|
||||
|
||||
|
||||
// Call-related instructions.
|
||||
def LLVM_CallOp : LLVM_VariadicOneResultOp<"call">;
|
||||
def LLVM_Call0Op : LLVM_ZeroResultOp<"call0", []>,
|
||||
Arguments<(ins Variadic<LLVM_Type>)>;
|
||||
def LLVM_CallOp : LLVM_Op<"call">, Arguments<(ins Variadic<LLVM_Type>)>,
|
||||
Results<(outs Variadic<LLVM_Type>)> {
|
||||
let builder = LLVM_TwoBuilders<
|
||||
LLVM_OneResultOpBuilder.builder,
|
||||
LLVM_ZeroResultOpBuilder.builder
|
||||
>.builder;
|
||||
|
||||
let verifier = [{
|
||||
if (getNumResults() > 1)
|
||||
return emitOpError("must have 0 or 1 result");
|
||||
return false;
|
||||
}];
|
||||
}
|
||||
def LLVM_ExtractValueOp : LLVM_OneResultOp<"extractvalue", [NoSideEffect]>,
|
||||
Arguments<(ins LLVM_Type)>;
|
||||
def LLVM_InsertValueOp : LLVM_OneResultOp<"insertvalue", [NoSideEffect]>,
|
||||
|
|
|
@ -441,18 +441,14 @@ struct OneToOneLLVMOpLowering : public LLVMLegalizationPattern<SourceOp> {
|
|||
unsigned numResults = op->getNumResults();
|
||||
auto *mlirContext = op->getContext();
|
||||
|
||||
// FIXME: using void here because there is a special case in the
|
||||
// builder... change this to use an empty type instead.
|
||||
auto voidType = LLVM::LLVMType::get(
|
||||
mlirContext, llvm::Type::getVoidTy(this->dialect.getLLVMContext()));
|
||||
auto packedType =
|
||||
numResults == 0
|
||||
? voidType
|
||||
: TypeConverter::pack(getTypes(op->getResults()),
|
||||
this->dialect.getLLVMModule(), *mlirContext);
|
||||
assert(
|
||||
packedType &&
|
||||
"type conversion failed, such operation should not have been matched");
|
||||
Type packedType;
|
||||
if (numResults != 0) {
|
||||
packedType =
|
||||
TypeConverter::pack(getTypes(op->getResults()),
|
||||
this->dialect.getLLVMModule(), *mlirContext);
|
||||
assert(packedType && "type conversion failed, such operation should not "
|
||||
"have been matched");
|
||||
}
|
||||
|
||||
auto newOp = rewriter.create<TargetOp>(op->getLoc(), packedType, operands,
|
||||
op->getAttrs());
|
||||
|
@ -525,53 +521,13 @@ struct SelectOpLowering
|
|||
: public OneToOneLLVMOpLowering<SelectOp, LLVM::SelectOp> {
|
||||
using Super::Super;
|
||||
};
|
||||
|
||||
// Refine the matcher for call operations that return one result or more.
|
||||
// Since tablegen'ed MLIR Ops cannot have variadic results, we separate calls
|
||||
// that have 0 or 1 result (LLVM calls cannot have more than 1).
|
||||
template <typename SourceOp>
|
||||
struct NonZeroResultCallLowering
|
||||
: public OneToOneLLVMOpLowering<SourceOp, LLVM::CallOp> {
|
||||
using OneToOneLLVMOpLowering<SourceOp, LLVM::CallOp>::OneToOneLLVMOpLowering;
|
||||
using Super = NonZeroResultCallLowering<SourceOp>;
|
||||
|
||||
PatternMatchResult match(Instruction *op) const override {
|
||||
if (op->getNumResults() > 0)
|
||||
return OneToOneLLVMOpLowering<SourceOp, LLVM::CallOp>::match(op);
|
||||
return this->matchFailure();
|
||||
}
|
||||
};
|
||||
|
||||
// Refine the matcher for call operations that return zero results.
|
||||
// Since tablegen'ed MLIR Ops cannot have variadic results, we separate calls
|
||||
// that have 0 or 1 result (LLVM calls cannot have more than 1).
|
||||
template <typename SourceOp>
|
||||
struct ZeroResultCallLowering
|
||||
: public OneToOneLLVMOpLowering<SourceOp, LLVM::Call0Op> {
|
||||
using OneToOneLLVMOpLowering<SourceOp, LLVM::Call0Op>::OneToOneLLVMOpLowering;
|
||||
using Super = ZeroResultCallLowering<SourceOp>;
|
||||
|
||||
PatternMatchResult match(Instruction *op) const override {
|
||||
if (op->getNumResults() == 0)
|
||||
return OneToOneLLVMOpLowering<SourceOp, LLVM::Call0Op>::match(op);
|
||||
return this->matchFailure();
|
||||
}
|
||||
};
|
||||
|
||||
struct Call0OpLowering : public ZeroResultCallLowering<CallOp> {
|
||||
using Super::Super;
|
||||
};
|
||||
struct CallOpLowering : public NonZeroResultCallLowering<CallOp> {
|
||||
using Super::Super;
|
||||
};
|
||||
struct CallIndirect0OpLowering : public ZeroResultCallLowering<CallIndirectOp> {
|
||||
struct CallOpLowering : public OneToOneLLVMOpLowering<CallOp, LLVM::CallOp> {
|
||||
using Super::Super;
|
||||
};
|
||||
struct CallIndirectOpLowering
|
||||
: public NonZeroResultCallLowering<CallIndirectOp> {
|
||||
: public OneToOneLLVMOpLowering<CallIndirectOp, LLVM::CallOp> {
|
||||
using Super::Super;
|
||||
};
|
||||
|
||||
struct ConstLLVMOpLowering
|
||||
: public OneToOneLLVMOpLowering<ConstantOp, LLVM::ConstantOp> {
|
||||
using Super::Super;
|
||||
|
@ -657,10 +613,12 @@ struct AllocOpLowering : public LLVMLegalizationPattern<AllocOp> {
|
|||
// descriptor.
|
||||
auto mallocNamedAttr = NamedAttribute{rewriter.getIdentifier("callee"),
|
||||
rewriter.getFunctionAttr(mallocFunc)};
|
||||
Value *allocated = rewriter.create<LLVM::CallOp>(
|
||||
op->getLoc(), getVoidPtrType(), ArrayRef<Value *>(cumulativeSize),
|
||||
llvm::makeArrayRef(mallocNamedAttr));
|
||||
|
||||
Value *allocated =
|
||||
rewriter
|
||||
.create<LLVM::CallOp>(op->getLoc(), getVoidPtrType(),
|
||||
ArrayRef<Value *>(cumulativeSize),
|
||||
llvm::makeArrayRef(mallocNamedAttr))
|
||||
->getResult(0);
|
||||
auto structElementType = TypeConverter::convert(elementType, getModule());
|
||||
auto elementPtrType = LLVM::LLVMType::get(
|
||||
op->getContext(), structElementType.cast<LLVM::LLVMType>()
|
||||
|
@ -734,8 +692,8 @@ struct DeallocOpLowering : public LLVMLegalizationPattern<DeallocOp> {
|
|||
op->getLoc(), getVoidPtrType(), bufferPtr);
|
||||
auto freeNamedAttr = NamedAttribute{rewriter.getIdentifier("callee"),
|
||||
rewriter.getFunctionAttr(freeFunc)};
|
||||
rewriter.create<LLVM::Call0Op>(op->getLoc(), casted,
|
||||
llvm::makeArrayRef(freeNamedAttr));
|
||||
rewriter.create<LLVM::CallOp>(op->getLoc(), casted,
|
||||
llvm::makeArrayRef(freeNamedAttr));
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
@ -1165,13 +1123,13 @@ protected:
|
|||
// FIXME: this should be tablegen'ed
|
||||
return ConversionListBuilder<
|
||||
AddFOpLowering, AddIOpLowering, AllocOpLowering, BranchOpLowering,
|
||||
Call0OpLowering, CallIndirect0OpLowering, CallIndirectOpLowering,
|
||||
CallOpLowering, CmpIOpLowering, CondBranchOpLowering,
|
||||
ConstLLVMOpLowering, DeallocOpLowering, DimOpLowering, DivISOpLowering,
|
||||
DivIUOpLowering, DivFOpLowering, LoadOpLowering, MemRefCastOpLowering,
|
||||
MulFOpLowering, MulIOpLowering, RemISOpLowering, RemIUOpLowering,
|
||||
RemFOpLowering, ReturnOpLowering, SelectOpLowering, StoreOpLowering,
|
||||
SubFOpLowering, SubIOpLowering>::build(&converterStorage, *llvmDialect);
|
||||
CallIndirectOpLowering, CallOpLowering, CmpIOpLowering,
|
||||
CondBranchOpLowering, ConstLLVMOpLowering, DeallocOpLowering,
|
||||
DimOpLowering, DivISOpLowering, DivIUOpLowering, DivFOpLowering,
|
||||
LoadOpLowering, MemRefCastOpLowering, MulFOpLowering, MulIOpLowering,
|
||||
RemISOpLowering, RemIUOpLowering, RemFOpLowering, ReturnOpLowering,
|
||||
SelectOpLowering, StoreOpLowering, SubFOpLowering,
|
||||
SubIOpLowering>::build(&converterStorage, *llvmDialect);
|
||||
}
|
||||
|
||||
// Convert types using the stored LLVM IR module.
|
||||
|
|
|
@ -263,14 +263,15 @@ bool ModuleTranslation::convertInstruction(const Instruction &inst,
|
|||
};
|
||||
|
||||
// Emit calls. If the called function has a result, remap the corresponding
|
||||
// value.
|
||||
// value. Note that LLVM IR dialect CallOp has either 0 or 1 result.
|
||||
if (auto op = inst.dyn_cast<LLVM::CallOp>()) {
|
||||
valueMapping[op->getResult()] = convertCall(inst);
|
||||
return false;
|
||||
}
|
||||
if (inst.isa<LLVM::Call0Op>()) {
|
||||
convertCall(inst);
|
||||
return false;
|
||||
llvm::Value *result = convertCall(inst);
|
||||
if (inst.getNumResults() != 0) {
|
||||
valueMapping[inst.getResult(0)] = result;
|
||||
return false;
|
||||
}
|
||||
// Check that LLVM call returns void for 0-result functions.
|
||||
return !result->getType()->isVoidTy();
|
||||
}
|
||||
|
||||
// Emit branches. We need to look up the remapped blocks and ignore the block
|
||||
|
|
|
@ -36,7 +36,7 @@ func @body(i32)
|
|||
func @indirect_const_call(%arg0: i32) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: @body : (!llvm<"i32">) -> ()} : () -> !llvm<"void (i32)*">
|
||||
%0 = constant @body : (i32) -> ()
|
||||
// CHECK-NEXT: "llvm.call0"(%0, %arg0) : (!llvm<"void (i32)*">, !llvm<"i32">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"(%0, %arg0) : (!llvm<"void (i32)*">, !llvm<"i32">) -> ()
|
||||
call_indirect %0(%arg0) : (i32) -> ()
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
return
|
||||
|
|
|
@ -34,7 +34,7 @@ func @mixed_alloc(%arg0: index, %arg1: index) -> memref<?x42x?xf32> {
|
|||
func @mixed_dealloc(%arg0: memref<?x42x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %1 = "llvm.bitcast"(%0) : (!llvm<"float*">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: "llvm.call0"(%1) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"(%1) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
dealloc %arg0 : memref<?x42x?xf32>
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
return
|
||||
|
@ -59,7 +59,7 @@ func @dynamic_alloc(%arg0: index, %arg1: index) -> memref<?x?xf32> {
|
|||
func @dynamic_dealloc(%arg0: memref<?x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %1 = "llvm.bitcast"(%0) : (!llvm<"float*">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: "llvm.call0"(%1) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"(%1) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
dealloc %arg0 : memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ func @static_alloc() -> memref<32x18xf32> {
|
|||
// CHECK-LABEL: func @static_dealloc(%arg0: !llvm<"float*">) {
|
||||
func @static_dealloc(%static: memref<10x8xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.bitcast"(%arg0) : (!llvm<"float*">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: "llvm.call0"(%0) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"(%0) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
dealloc %static : memref<10x8xf32>
|
||||
return
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ func @simple_loop() {
|
|||
cond_br %1, ^bb3, ^bb4
|
||||
|
||||
// CHECK: ^bb3: // pred: ^bb2
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}) {callee: @body : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @body : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
|
@ -51,7 +51,7 @@ func @simple_loop() {
|
|||
}
|
||||
|
||||
// CHECK-LABEL: func @simple_caller() {
|
||||
// CHECK-NEXT: "llvm.call0"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: }
|
||||
func @simple_caller() {
|
||||
|
@ -61,8 +61,8 @@ func @simple_caller() {
|
|||
}
|
||||
|
||||
// CHECK-LABEL: func @ml_caller() {
|
||||
// CHECK-NEXT: "llvm.call0"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.call0"() {callee: @more_imperfectly_nested_loops : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.call"() {callee: @more_imperfectly_nested_loops : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: }
|
||||
func @ml_caller() {
|
||||
|
@ -160,7 +160,7 @@ func @imperfectly_nested_loops() {
|
|||
cond_br %1, ^bb3, ^bb8
|
||||
|
||||
// CHECK-NEXT: ^bb3:
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.br"()[^bb4] : () -> ()
|
||||
^bb3: // pred: ^bb2
|
||||
call @pre(%0) : (index) -> ()
|
||||
|
@ -183,7 +183,7 @@ func @imperfectly_nested_loops() {
|
|||
cond_br %3, ^bb6, ^bb7
|
||||
|
||||
// CHECK-NEXT: ^bb6: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}, {{.*}}) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}, {{.*}}) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb5({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
|
@ -194,7 +194,7 @@ func @imperfectly_nested_loops() {
|
|||
br ^bb5(%4 : index)
|
||||
|
||||
// CHECK-NEXT: ^bb7: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
|
@ -227,7 +227,7 @@ func @body3(index, index)
|
|||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb3, ^bb12] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: ^bb3: // pred: ^bb2
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.br"()[^bb4] : () -> ()
|
||||
// CHECK-NEXT: ^bb4: // pred: ^bb3
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 7 : index} : () -> !llvm<"i64">
|
||||
|
@ -237,12 +237,12 @@ func @body3(index, index)
|
|||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb6, ^bb7] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: ^bb6: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}, {{.*}}) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}, {{.*}}) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb5({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb7: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}) {callee: @mid : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @mid : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.br"()[^bb8] : () -> ()
|
||||
// CHECK-NEXT: ^bb8: // pred: ^bb7
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 18 : index} : () -> !llvm<"i64">
|
||||
|
@ -252,12 +252,12 @@ func @body3(index, index)
|
|||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb10, ^bb11] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: ^bb10: // pred: ^bb9
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}, {{.*}}) {callee: @body3 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}, {{.*}}) {callee: @body3 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 3 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb9({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb11: // pred: ^bb9
|
||||
// CHECK-NEXT: "llvm.call0"({{.*}}) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
|
|
|
@ -51,7 +51,7 @@ func @simple_loop() {
|
|||
// CHECK-NEXT: %{{[0-9]+}} = add i64 %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: br label %[[SIMPLE_bb2]]
|
||||
^bb3: // pred: ^bb2
|
||||
"llvm.call0"(%2) {callee: @body : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.call"(%2) {callee: @body : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
%4 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%5 = "llvm.add"(%2, %4) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%5 : !llvm<"i64">)] : () -> ()
|
||||
|
@ -67,7 +67,7 @@ func @simple_loop() {
|
|||
// CHECK-NEXT: ret void
|
||||
// CHECK-NEXT: }
|
||||
func @simple_caller() {
|
||||
"llvm.call0"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
"llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
"llvm.return"() : () -> ()
|
||||
}
|
||||
|
||||
|
@ -84,8 +84,8 @@ func @simple_caller() {
|
|||
// CHECK-NEXT: ret void
|
||||
// CHECK-NEXT: }
|
||||
func @ml_caller() {
|
||||
"llvm.call0"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
"llvm.call0"() {callee: @more_imperfectly_nested_loops : () -> ()} : () -> ()
|
||||
"llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
"llvm.call"() {callee: @more_imperfectly_nested_loops : () -> ()} : () -> ()
|
||||
"llvm.return"() : () -> ()
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ func @imperfectly_nested_loops() {
|
|||
// CHECK-NEXT: call void @pre(i64 %3)
|
||||
// CHECK-NEXT: br label %[[IMPER_bb4:[0-9]+]]
|
||||
^bb3: // pred: ^bb2
|
||||
"llvm.call0"(%2) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.call"(%2) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.br"()[^bb4] : () -> ()
|
||||
|
||||
// CHECK: <label>:[[IMPER_bb4]]:
|
||||
|
@ -196,7 +196,7 @@ func @imperfectly_nested_loops() {
|
|||
// CHECK-NEXT: %11 = add i64 %8, 2
|
||||
// CHECK-NEXT: br label %[[IMPER_bb5]]
|
||||
^bb6: // pred: ^bb5
|
||||
"llvm.call0"(%2, %6) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
"llvm.call"(%2, %6) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%8 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%9 = "llvm.add"(%6, %8) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb5(%9 : !llvm<"i64">)] : () -> ()
|
||||
|
@ -206,7 +206,7 @@ func @imperfectly_nested_loops() {
|
|||
// CHECK-NEXT: %13 = add i64 %3, 1
|
||||
// CHECK-NEXT: br label %[[IMPER_bb2]]
|
||||
^bb7: // pred: ^bb5
|
||||
"llvm.call0"(%2) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.call"(%2) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
%10 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%11 = "llvm.add"(%2, %10) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%11 : !llvm<"i64">)] : () -> ()
|
||||
|
@ -275,7 +275,7 @@ func @more_imperfectly_nested_loops() {
|
|||
%3 = "llvm.icmp"(%2, %1) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%3)[^bb3, ^bb12] : (!llvm<"i1">) -> ()
|
||||
^bb3: // pred: ^bb2
|
||||
"llvm.call0"(%2) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.call"(%2) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.br"()[^bb4] : () -> ()
|
||||
^bb4: // pred: ^bb3
|
||||
%4 = "llvm.constant"() {value: 7 : index} : () -> !llvm<"i64">
|
||||
|
@ -285,12 +285,12 @@ func @more_imperfectly_nested_loops() {
|
|||
%7 = "llvm.icmp"(%6, %5) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%7)[^bb6, ^bb7] : (!llvm<"i1">) -> ()
|
||||
^bb6: // pred: ^bb5
|
||||
"llvm.call0"(%2, %6) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
"llvm.call"(%2, %6) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%8 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%9 = "llvm.add"(%6, %8) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb5(%9 : !llvm<"i64">)] : () -> ()
|
||||
^bb7: // pred: ^bb5
|
||||
"llvm.call0"(%2) {callee: @mid : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.call"(%2) {callee: @mid : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.br"()[^bb8] : () -> ()
|
||||
^bb8: // pred: ^bb7
|
||||
%10 = "llvm.constant"() {value: 18 : index} : () -> !llvm<"i64">
|
||||
|
@ -300,12 +300,12 @@ func @more_imperfectly_nested_loops() {
|
|||
%13 = "llvm.icmp"(%12, %11) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%13)[^bb10, ^bb11] : (!llvm<"i1">) -> ()
|
||||
^bb10: // pred: ^bb9
|
||||
"llvm.call0"(%2, %12) {callee: @body3 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
"llvm.call"(%2, %12) {callee: @body3 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%14 = "llvm.constant"() {value: 3 : index} : () -> !llvm<"i64">
|
||||
%15 = "llvm.add"(%12, %14) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb9(%15 : !llvm<"i64">)] : () -> ()
|
||||
^bb11: // pred: ^bb9
|
||||
"llvm.call0"(%2) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.call"(%2) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
%16 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%17 = "llvm.add"(%2, %16) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%17 : !llvm<"i64">)] : () -> ()
|
||||
|
@ -754,7 +754,7 @@ func @ops(%arg0: !llvm<"float">, %arg1: !llvm<"float">, %arg2: !llvm<"i32">, %ar
|
|||
func @indirect_const_call(%arg0: !llvm<"i64">) {
|
||||
// CHECK-NEXT: call void @body(i64 %0)
|
||||
%0 = "llvm.constant"() {value: @body : (!llvm<"i64">) -> ()} : () -> !llvm<"void (i64)*">
|
||||
"llvm.call0"(%0, %arg0) : (!llvm<"void (i64)*">, !llvm<"i64">) -> ()
|
||||
"llvm.call"(%0, %arg0) : (!llvm<"void (i64)*">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: ret void
|
||||
"llvm.return"() : () -> ()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue