diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index db3fb0b90464d..f58dde589aaf5 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -348,6 +348,26 @@ def hlfir_ConcatOp : hlfir_Op<"concat", let hasVerifier = 1; } +def hlfir_CmpCharOp : hlfir_Op<"cmpchar", + [DeclareOpInterfaceMethods]> { + let summary = "compare two characters"; + let description = [{ + Compare two character strings of a same character kind. + }]; + + let arguments = (ins Arith_CmpIPredicateAttr:$predicate, + AnyScalarCharacterEntity:$lchr, + AnyScalarCharacterEntity:$rchr); + + let results = (outs I1); + + let assemblyFormat = [{ + $predicate $lchr $rchr attr-dict `:` functional-type(operands, results) + }]; + + let hasVerifier = 1; +} + def hlfir_AllOp : hlfir_Op<"all", [DeclareOpInterfaceMethods]> { let summary = "ALL transformational intrinsic"; let description = [{ diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 3c5095da0145a..964d183631186 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -820,6 +820,40 @@ void hlfir::ConcatOp::getEffects( getIntrinsicEffects(getOperation(), effects); } +//===----------------------------------------------------------------------===// +// CmpCharOp +//===----------------------------------------------------------------------===// + +llvm::LogicalResult hlfir::CmpCharOp::verify() { + mlir::Value lchr = getLchr(); + mlir::Value rchr = getRchr(); + + unsigned kind = getCharacterKind(lchr.getType()); + if (kind != getCharacterKind(rchr.getType())) + return emitOpError("character arguments must have the same KIND"); + + switch (getPredicate()) { + case mlir::arith::CmpIPredicate::slt: + case mlir::arith::CmpIPredicate::sle: + case mlir::arith::CmpIPredicate::eq: + case mlir::arith::CmpIPredicate::ne: + case mlir::arith::CmpIPredicate::sgt: + case mlir::arith::CmpIPredicate::sge: + break; + default: + return emitOpError("expected signed predicate"); + } + + return mlir::success(); +} + +void hlfir::CmpCharOp::getEffects( + llvm::SmallVectorImpl< + mlir::SideEffects::EffectInstance> + &effects) { + getIntrinsicEffects(getOperation(), effects); +} + //===----------------------------------------------------------------------===// // NumericalReductionOp //===----------------------------------------------------------------------===// diff --git a/flang/test/HLFIR/invalid.fir b/flang/test/HLFIR/invalid.fir index 0f54a0250294b..b4baedb1e6477 100644 --- a/flang/test/HLFIR/invalid.fir +++ b/flang/test/HLFIR/invalid.fir @@ -296,6 +296,17 @@ func.func @bad_concat_4(%arg0: !fir.ref>) { return } +// ----- +func.func @bad_cmpchar_1(%arg0: !fir.ref>, %arg1: !fir.ref>) { + // expected-error@+1 {{'hlfir.cmpchar' op character arguments must have the same KIND}} + %0 = hlfir.cmpchar ne %arg0 %arg1 : (!fir.ref>, !fir.ref>) -> i1 +} + +func.func @bad_cmpchar_2(%arg0: !fir.ref>, %arg1: !fir.ref>) { + // expected-error@+1 {{'hlfir.cmpchar' op expected signed predicate}} + %0 = hlfir.cmpchar ugt %arg0 %arg1 : (!fir.ref>, !fir.ref>) -> i1 +} + // ----- func.func @bad_any1(%arg0: !hlfir.expr>) { // expected-error@+1 {{'hlfir.any' op result must have the same element type as MASK argument}}