Lower standard DivF and RemF operations to the LLVM IR dialect

Add support for lowering DivF and RemF to LLVM::FDiv and LLMV::FRem
respectively.  The lowering is a trivial one-to-one transformation.
The corresponding operations already existed in the LLVM IR dialect and can be
lowered to the LLVM IR proper.  Add the necessary tests for scalar and vector
forms.

PiperOrigin-RevId: 234984608
This commit is contained in:
Alex Zinenko 2019-02-21 06:30:53 -08:00 committed by jpienaar
parent 1cc9305c71
commit c98a87cc06
4 changed files with 46 additions and 4 deletions

View File

@ -489,6 +489,12 @@ struct SubFOpLowering : public OneToOneLLVMOpLowering<SubFOp, LLVM::FSubOp> {
struct MulFOpLowering : public OneToOneLLVMOpLowering<MulFOp, LLVM::FMulOp> {
using Super::Super;
};
struct DivFOpLowering : public OneToOneLLVMOpLowering<DivFOp, LLVM::FDivOp> {
using Super::Super;
};
struct RemFOpLowering : public OneToOneLLVMOpLowering<RemFOp, LLVM::FRemOp> {
using Super::Super;
};
struct CmpIOpLowering : public OneToOneLLVMOpLowering<CmpIOp, LLVM::ICmpOp> {
using Super::Super;
};
@ -1049,10 +1055,10 @@ protected:
Call0OpLowering, CallIndirect0OpLowering, CallIndirectOpLowering,
CallOpLowering, CmpIOpLowering, CondBranchOpLowering,
ConstLLVMOpLowering, DeallocOpLowering, DimOpLowering, DivISOpLowering,
DivIUOpLowering, LoadOpLowering, MemRefCastOpLowering, MulFOpLowering,
MulIOpLowering, RemISOpLowering, RemIUOpLowering, ReturnOpLowering,
SelectOpLowering, StoreOpLowering, SubFOpLowering,
SubIOpLowering>::build(&converterStorage, *llvmDialect);
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.

View File

@ -199,6 +199,24 @@ func @standard_instrs(tensor<4x4x?xf32>, f32, i32, index) {
// CHECK: %{{[0-9]+}} = remiu %arg2, %arg2 : i32
%45 = "remiu"(%i, %i) : (i32, i32) -> i32
// CHECK: %{{[0-9]+}} = divf %arg1, %arg1 : f32
%46 = "divf"(%f, %f) : (f32,f32) -> f32
// CHECK: %{{[0-9]+}} = divf %arg1, %arg1 : f32
%47 = divf %f, %f : f32
// CHECK: %{{[0-9]+}} = divf %arg0, %arg0 : tensor<4x4x?xf32>
%48 = divf %t, %t : tensor<4x4x?xf32>
// CHECK: %{{[0-9]+}} = remf %arg1, %arg1 : f32
%49 = "remf"(%f, %f) : (f32,f32) -> f32
// CHECK: %{{[0-9]+}} = remf %arg1, %arg1 : f32
%50 = remf %f, %f : f32
// CHECK: %{{[0-9]+}} = remf %arg0, %arg0 : tensor<4x4x?xf32>
%51 = remf %t, %t : tensor<4x4x?xf32>
return
}

View File

@ -371,6 +371,10 @@ func @vector_ops(vector<4xf32>, vector<4xi1>, vector<4xi64>) -> vector<4xf32> {
%5 = remis %arg2, %arg2 : vector<4xi64>
// CHECK-NEXT: {{.*}} = "llvm.urem"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
%6 = remiu %arg2, %arg2 : vector<4xi64>
// CHECK-NEXT: {{.*}} = "llvm.fdiv"(%arg0, {{.*}}) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
%7 = divf %arg0, %0 : vector<4xf32>
// CHECK-NEXT: {{.*}} = "llvm.frem"(%arg0, {{.*}}) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
%8 = remf %arg0, %0 : vector<4xf32>
return %1 : vector<4xf32>
}
@ -393,6 +397,10 @@ func @ops(f32, f32, i32, i32) -> (f32, i32) {
%7 = remiu %arg2, %arg3 : i32
// CHECK-NEXT: {{.*}} = "llvm.select"({{.*}}, %arg2, %arg3) : (!llvm<"i1">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
%8 = select %2, %arg2, %arg3 : i32
// CHECK-NEXT: {{.*}} = "llvm.fdiv"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
%9 = divf %arg0, %arg1 : f32
// CHECK-NEXT: {{.*}} = "llvm.frem"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
%10 = remf %arg0, %arg1 : f32
return %0, %4 : f32, i32
}

View File

@ -707,6 +707,10 @@ func @vector_ops(%arg0: !llvm<"<4 x float>">, %arg1: !llvm<"<4 x i1>">, %arg2: !
%5 = "llvm.srem"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
// CHECK-NEXT: %9 = urem <4 x i64> %2, %2
%6 = "llvm.urem"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
// CHECK-NEXT: %10 = fdiv <4 x float> %0, <float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01>
%7 = "llvm.fdiv"(%arg0, %0) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
// CHECK-NEXT: %11 = frem <4 x float> %0, <float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01>
%8 = "llvm.frem"(%arg0, %0) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
// CHECK-NEXT: ret <4 x float> %4
"llvm.return"(%1) : (!llvm<"<4 x float>">) -> ()
}
@ -733,6 +737,12 @@ func @ops(%arg0: !llvm<"float">, %arg1: !llvm<"float">, %arg2: !llvm<"i32">, %ar
%8 = "llvm.undef"() : () -> !llvm<"{ float, i32 }">
%9 = "llvm.insertvalue"(%8, %0) {position: [0]} : (!llvm<"{ float, i32 }">, !llvm<"float">) -> !llvm<"{ float, i32 }">
%10 = "llvm.insertvalue"(%9, %3) {position: [1]} : (!llvm<"{ float, i32 }">, !llvm<"i32">) -> !llvm<"{ float, i32 }">
// CHECK: %15 = fdiv float %0, %1
%11 = "llvm.fdiv"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
// CHECK-NEXT: %16 = frem float %0, %1
%12 = "llvm.frem"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
"llvm.return"(%10) : (!llvm<"{ float, i32 }">) -> ()
}