From f9bd871d32059680c1dbad3fb934bb8a94ac3aa5 Mon Sep 17 00:00:00 2001 From: Evandro Menezes Date: Wed, 7 Mar 2018 22:35:32 +0000 Subject: [PATCH] [AArch64] Adjust the cost of integer vector division Since there is no instruction for integer vector division, factor in the cost of singling out each element to be used with the scalar division instruction. Differential revision: https://reviews.llvm.org/D43974 llvm-svn: 326955 --- .../Target/AArch64/AArch64TargetTransformInfo.cpp | 60 ++++++++++++++-------- llvm/test/Analysis/CostModel/AArch64/div.ll | 38 ++++++++++++++ 2 files changed, 76 insertions(+), 22 deletions(-) create mode 100644 llvm/test/Analysis/CostModel/AArch64/div.ll diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index aafcd7f..c2204af 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -493,32 +493,48 @@ int AArch64TTIImpl::getArithmeticInstrCost( int ISD = TLI->InstructionOpcodeToISD(Opcode); - if (ISD == ISD::SDIV && - Opd2Info == TargetTransformInfo::OK_UniformConstantValue && - Opd2PropInfo == TargetTransformInfo::OP_PowerOf2) { - // On AArch64, scalar signed division by constants power-of-two are - // normally expanded to the sequence ADD + CMP + SELECT + SRA. - // The OperandValue properties many not be same as that of previous - // operation; conservatively assume OP_None. - Cost += getArithmeticInstrCost(Instruction::Add, Ty, Opd1Info, Opd2Info, - TargetTransformInfo::OP_None, - TargetTransformInfo::OP_None); - Cost += getArithmeticInstrCost(Instruction::Sub, Ty, Opd1Info, Opd2Info, - TargetTransformInfo::OP_None, - TargetTransformInfo::OP_None); - Cost += getArithmeticInstrCost(Instruction::Select, Ty, Opd1Info, Opd2Info, - TargetTransformInfo::OP_None, - TargetTransformInfo::OP_None); - Cost += getArithmeticInstrCost(Instruction::AShr, Ty, Opd1Info, Opd2Info, - TargetTransformInfo::OP_None, - TargetTransformInfo::OP_None); - return Cost; - } - switch (ISD) { default: return Cost + BaseT::getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, Opd1PropInfo, Opd2PropInfo); + case ISD::SDIV: + if (Opd2Info == TargetTransformInfo::OK_UniformConstantValue && + Opd2PropInfo == TargetTransformInfo::OP_PowerOf2) { + // On AArch64, scalar signed division by constants power-of-two are + // normally expanded to the sequence ADD + CMP + SELECT + SRA. + // The OperandValue properties many not be same as that of previous + // operation; conservatively assume OP_None. + Cost += getArithmeticInstrCost(Instruction::Add, Ty, Opd1Info, Opd2Info, + TargetTransformInfo::OP_None, + TargetTransformInfo::OP_None); + Cost += getArithmeticInstrCost(Instruction::Sub, Ty, Opd1Info, Opd2Info, + TargetTransformInfo::OP_None, + TargetTransformInfo::OP_None); + Cost += getArithmeticInstrCost(Instruction::Select, Ty, Opd1Info, Opd2Info, + TargetTransformInfo::OP_None, + TargetTransformInfo::OP_None); + Cost += getArithmeticInstrCost(Instruction::AShr, Ty, Opd1Info, Opd2Info, + TargetTransformInfo::OP_None, + TargetTransformInfo::OP_None); + return Cost; + } + LLVM_FALLTHROUGH; + case ISD::UDIV: + Cost += BaseT::getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, + Opd1PropInfo, Opd2PropInfo); + if (Ty->isVectorTy()) { + // On AArch64, vector divisions are not supported natively and are + // expanded into scalar divisions of each pair of elements. + Cost += getArithmeticInstrCost(Instruction::ExtractElement, Ty, Opd1Info, + Opd2Info, Opd1PropInfo, Opd2PropInfo); + Cost += getArithmeticInstrCost(Instruction::InsertElement, Ty, Opd1Info, + Opd2Info, Opd1PropInfo, Opd2PropInfo); + // TODO: if one of the arguments is scalar, then it's not necessary to + // double the cost of handling the vector elements. + Cost += Cost; + } + return Cost; + case ISD::ADD: case ISD::MUL: case ISD::XOR: diff --git a/llvm/test/Analysis/CostModel/AArch64/div.ll b/llvm/test/Analysis/CostModel/AArch64/div.ll new file mode 100644 index 0000000..50f7117 --- /dev/null +++ b/llvm/test/Analysis/CostModel/AArch64/div.ll @@ -0,0 +1,38 @@ +; RUN: opt -cost-model -analyze -mtriple=aarch64--linux-gnu < %s | FileCheck %s + +; Verify the cost of integer division instructions. + +define i32 @sdivs1i32(i32 %a, i32 %b) { +; CHECK-LABEL: 'Cost Model Analysis' for function 'sdivs1i32': +; CHECK: Found an estimated cost of 1 for instruction: %c = sdiv i32 %a, %b + %c = sdiv i32 %a, %b + ret i32 %c +} + +define i64 @sdivs1i64(i64 %a, i64 %b) { +; CHECK-LABEL: 'Cost Model Analysis' for function 'sdivs1i64': +; CHECK: Found an estimated cost of 1 for instruction: %c = sdiv i64 %a, %b + %c = sdiv i64 %a, %b + ret i64 %c +} + +define <2 x i32> @sdivv2i32(<2 x i32> %a, <2 x i32> %b) { +; CHECK-LABEL: 'Cost Model Analysis' for function 'sdivv2i32': +; CHECK: Found an estimated cost of 24 for instruction: %c = sdiv <2 x i32> %a, %b + %c = sdiv <2 x i32> %a, %b + ret <2 x i32> %c +} + +define <2 x i64> @sdivv2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK-LABEL: 'Cost Model Analysis' for function 'sdivv2i64': +; CHECK: Found an estimated cost of 24 for instruction: %c = sdiv <2 x i64> %a, %b + %c = sdiv <2 x i64> %a, %b + ret <2 x i64> %c +} + +define <4 x i32> @sdivv4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: 'Cost Model Analysis' for function 'sdivv4i32': +; CHECK: Found an estimated cost of 52 for instruction: %c = sdiv <4 x i32> %a, %b + %c = sdiv <4 x i32> %a, %b + ret <4 x i32> %c +} -- 2.7.4