Index: llvm/include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -1027,7 +1027,20 @@ } case Instruction::Load: { auto *LI = cast(U); - return TargetTTI->getMemoryOpCost(Opcode, U->getType(), LI->getAlign(), + Type *LoadType = U->getType(); + // If there is a non-register sized type, the cost estimation may expand + // it to be several instructions to load into multiple registers on the + // target. But, if the only use of the load is a trunc instruction to a + // register sized type, the instruction selector can combine these + // instructions to be a single load. So, in this case, we use the + // destination type of the trunc instruction rather than the load to + // accurately estimate the cost of this load instruction. + if (CostKind == TTI::TCK_CodeSize && LI->hasOneUse() && + !LoadType->isVectorTy()) { + if (const TruncInst *TI = dyn_cast(*LI->user_begin())) + LoadType = TI->getDestTy(); + } + return TargetTTI->getMemoryOpCost(Opcode, LoadType, LI->getAlign(), LI->getPointerAddressSpace(), CostKind, I); } Index: llvm/test/Analysis/CostModel/AArch64/load-to-trunc.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CostModel/AArch64/load-to-trunc.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; Check memory cost model action for a load of an unusually sized integer +; follow by and a trunc to a register sized integer gives a cost of 1 rather +; than the expanded cost if it is not. + +; RUN: opt -cost-model -cost-kind=code-size -analyze -mtriple=aarch64--linux-gnu < %s | FileCheck %s --check-prefix=CHECK + +; Check that cost is 1 for unusual load to register sized load. +define i32 @loadUnusualIntegerWithTrunc(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualIntegerWithTrunc' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %trunc = trunc i128 %out to i32 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %trunc +; + %out = load i128, i128* %ptr + %trunc = trunc i128 %out to i32 + ret i32 %trunc +} + +define i128 @loadUnusualInteger(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualInteger' +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i128 %out +; + %out = load i128, i128* %ptr + ret i128 %out +} Index: llvm/test/Analysis/CostModel/AMDGPU/load-to-trunc.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CostModel/AMDGPU/load-to-trunc.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; Check memory cost model action for a load of an unusually sized integer +; follow by and a trunc to a register sized integer gives a cost of 1 rather +; than the expanded cost if it is not. + +; RUN: opt -cost-model -cost-kind=code-size -analyze -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s --check-prefix=CHECK + +; Check that cost is 1 for unusual load to register sized load. +define i32 @loadUnusualIntegerWithTrunc(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualIntegerWithTrunc' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %trunc = trunc i128 %out to i32 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %trunc +; + %out = load i128, i128* %ptr + %trunc = trunc i128 %out to i32 + ret i32 %trunc +} + +define i128 @loadUnusualInteger(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualInteger' +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i128 %out +; + %out = load i128, i128* %ptr + ret i128 %out +} Index: llvm/test/Analysis/CostModel/ARM/load-to-trunc.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CostModel/ARM/load-to-trunc.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; Check memory cost model action for a load of an unusually sized integer +; follow by and a trunc to a register sized integer gives a cost of 1 rather +; than the expanded cost if it is not. Currently, this target does not have +; that expansion. + +; RUN: opt -cost-model -cost-kind=code-size -analyze -mtriple=armv8r-none-eabi < %s | FileCheck %s --check-prefix=CHECK + +; Check that cost is 1 for unusual load to register sized load. +define i32 @loadUnusualIntegerWithTrunc(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualIntegerWithTrunc' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %trunc = trunc i128 %out to i32 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %trunc +; + %out = load i128, i128* %ptr + %trunc = trunc i128 %out to i32 + ret i32 %trunc +} + +define i128 @loadUnusualInteger(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualInteger' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i128 %out +; + %out = load i128, i128* %ptr + ret i128 %out +} Index: llvm/test/Analysis/CostModel/PowerPC/load-to-trunc.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CostModel/PowerPC/load-to-trunc.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; Check memory cost model action for a load of an unusually sized integer +; follow by and a trunc to a register sized integer gives a cost of 1 rather +; than the expanded cost if it is not. +; RUN: opt -cost-model -cost-kind=code-size -analyze -mtriple=powerpc64-unknown-linux-gnu < %s | FileCheck %s --check-prefix=CHECK + +; Check that cost is 1 for unusual load to register sized load. +define i32 @loadUnusualIntegerWithTrunc(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualIntegerWithTrunc' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %trunc = trunc i128 %out to i32 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %trunc +; + %out = load i128, i128* %ptr + %trunc = trunc i128 %out to i32 + ret i32 %trunc +} + +define i128 @loadUnusualInteger(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualInteger' +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i128 %out +; + %out = load i128, i128* %ptr + ret i128 %out +} Index: llvm/test/Analysis/CostModel/RISCV/load-to-trunc.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CostModel/RISCV/load-to-trunc.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; Check memory cost model action for a load of an unusually sized integer +; follow by and a trunc to a register sized integer gives a cost of 1 rather +; than the expanded cost if it is not. + +; RUN: opt -cost-model -cost-kind=code-size -analyze -mtriple=riscv64 < %s | FileCheck %s --check-prefix=CHECK + +; Check that cost is 1 for unusual load to register sized load. +define i32 @loadUnusualIntegerWithTrunc(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualIntegerWithTrunc' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %trunc = trunc i128 %out to i32 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %trunc +; + %out = load i128, i128* %ptr + %trunc = trunc i128 %out to i32 + ret i32 %trunc +} + +define i128 @loadUnusualInteger(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualInteger' +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i128 %out +; + %out = load i128, i128* %ptr + ret i128 %out +} Index: llvm/test/Analysis/CostModel/SystemZ/load-to-trunc.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CostModel/SystemZ/load-to-trunc.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; Check memory cost model action for a load of an unusually sized integer +; follow by and a trunc to a register sized integer gives a cost of 1 rather +; than the expanded cost if it is not. This target does not currently perform +; the expansion in the cost modelling. +; RUN: opt -cost-model -cost-kind=code-size -analyze -mtriple=systemz-unknown < %s | FileCheck %s --check-prefix=CHECK + +; Check that cost is 1 for unusual load to register sized load. +define i32 @loadUnusualIntegerWithTrunc(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualIntegerWithTrunc' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %trunc = trunc i128 %out to i32 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %trunc +; + %out = load i128, i128* %ptr + %trunc = trunc i128 %out to i32 + ret i32 %trunc +} + +define i128 @loadUnusualInteger(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualInteger' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i128 %out +; + %out = load i128, i128* %ptr + ret i128 %out +} Index: llvm/test/Analysis/CostModel/X86/load-to-trunc.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CostModel/X86/load-to-trunc.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; Check memory cost model action for a load of an unusually sized integer +; follow by and a trunc to a register sized integer gives a cost of 1 rather +; than the expanded cost. Currently the x86 code size cost model does not use +; the expanded cost and only assigns a cost of 1 to each load. + +; RUN: opt -cost-model -cost-kind=code-size -analyze -mtriple=x86_64--linux-gnu < %s | FileCheck %s --check-prefix=CHECK + +; Check that cost is 1 for unusual load to register sized load. +define i32 @loadUnusualIntegerWithTrunc(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualIntegerWithTrunc' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %trunc = trunc i128 %out to i32 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %trunc +; + %out = load i128, i128* %ptr + %trunc = trunc i128 %out to i32 + ret i32 %trunc +} + +define i128 @loadUnusualInteger(i128* %ptr) { +; CHECK-LABEL: 'loadUnusualInteger' +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %out = load i128, i128* %ptr, align 4 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i128 %out +; + %out = load i128, i128* %ptr + ret i128 %out +}