This reverts commit f80c0baf058dbdc5 and 94eade61a02ae5. Recommit a small fix for targets using prefersVectorizedAddressing. Original message: Update VPReplicateRecipe::computeCost to compute costs of more replicating loads/stores. There are 2 cases that require extra checks to match the legacy cost model: 1. If the pointer is based on an induction, the legacy cost model passes its SCEV to getAddressComputationCost. In those cases, still fall back to the legacy cost. SCEV computations will be added as follow-up 2. If a load is used as part of an address of another load, the legacy cost model skips the scalarization overhead. Those cases are currently handled by a usedByLoadOrStore helper. Note that getScalarizationOverhead also needs updating, because when the legacy cost model computes the scalarization overhead, scalars have not been collected yet, so we can't each for replicating recipes to skip their cost, except other loads. This again can be further improved by modeling inserts/extracts explicitly and consistently, and compute costs for those operations directly where needed. PR: https://github.com/llvm/llvm-project/pull/160053
85 lines
3.3 KiB
LLVM
85 lines
3.3 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: opt -p loop-vectorize -S %s | FileCheck %s
|
|
|
|
target triple = "armv7-unknown-linux-gnueabihf"
|
|
|
|
define void @replicating_load_used_by_other_load(i32 %arg, ptr %a, i32 %b) {
|
|
; CHECK-LABEL: define void @replicating_load_used_by_other_load(
|
|
; CHECK-SAME: i32 [[ARG:%.*]], ptr [[A:%.*]], i32 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[ARG]], %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[IV]], 1
|
|
; CHECK-NEXT: [[AND_1:%.*]] = and i32 [[IV]], 1
|
|
; CHECK-NEXT: [[SHL_1:%.*]] = shl i32 [[IV]], 2
|
|
; CHECK-NEXT: [[SHL_2:%.*]] = shl i32 [[IV]], 1
|
|
; CHECK-NEXT: [[AND_2:%.*]] = and i32 [[SHL_2]], 2
|
|
; CHECK-NEXT: [[OR_1:%.*]] = or i32 [[AND_2]], [[AND_1]]
|
|
; CHECK-NEXT: [[OR_2:%.*]] = or i32 [[OR_1]], [[SHL_1]]
|
|
; CHECK-NEXT: [[XOR_1:%.*]] = xor i32 [[B]], [[OR_2]]
|
|
; CHECK-NEXT: [[XOR_2:%.*]] = xor i32 [[XOR_1]], [[ARG]]
|
|
; CHECK-NEXT: [[SHR_2:%.*]] = lshr i32 [[SHL_1]], 1
|
|
; CHECK-NEXT: [[XOR_3:%.*]] = xor i32 [[SHR]], [[ARG]]
|
|
; CHECK-NEXT: [[AND_3:%.*]] = and i32 [[XOR_3]], 1
|
|
; CHECK-NEXT: [[AND_4:%.*]] = and i32 [[IV]], 2147483646
|
|
; CHECK-NEXT: [[OR_3:%.*]] = or i32 [[AND_3]], [[AND_4]]
|
|
; CHECK-NEXT: [[AND_5:%.*]] = and i32 [[IV]], 254
|
|
; CHECK-NEXT: [[SHL_3:%.*]] = shl i32 [[OR_3]], 1
|
|
; CHECK-NEXT: [[XOR_4:%.*]] = xor i32 [[SHL_3]], 2
|
|
; CHECK-NEXT: [[OR_4:%.*]] = or i32 [[AND_5]], [[XOR_4]]
|
|
; CHECK-NEXT: [[XOR_5:%.*]] = xor i32 [[SHR_2]], [[OR_4]]
|
|
; CHECK-NEXT: [[XOR_6:%.*]] = xor i32 [[XOR_5]], [[XOR_2]]
|
|
; CHECK-NEXT: [[AND_6:%.*]] = and i32 [[XOR_6]], 255
|
|
; CHECK-NEXT: [[XOR_7:%.*]] = xor i32 [[AND_6]], 1
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i32 [[XOR_7]]
|
|
; CHECK-NEXT: [[LD:%.*]] = load i8, ptr [[GEP]], align 1
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[LD]] to i32
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i32, ptr null, i32 [[ZEXT]]
|
|
; CHECK-NEXT: store i32 0, ptr [[GEP_2]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[IV_NEXT]], 100
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[LOOP]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ %iv.next, %loop ], [ %arg, %entry ]
|
|
%shr = lshr i32 %iv, 1
|
|
%and.1 = and i32 %iv, 1
|
|
%shl.1 = shl i32 %iv, 2
|
|
%shl.2 = shl i32 %iv, 1
|
|
%and.2 = and i32 %shl.2, 2
|
|
%or.1 = or i32 %and.2, %and.1
|
|
%or.2 = or i32 %or.1, %shl.1
|
|
%xor.1 = xor i32 %b, %or.2
|
|
%xor.2 = xor i32 %xor.1, %arg
|
|
%shr.2 = lshr i32 %shl.1, 1
|
|
%xor.3 = xor i32 %shr, %arg
|
|
%and.3 = and i32 %xor.3, 1
|
|
%and.4 = and i32 %iv, 2147483646
|
|
%or.3 = or i32 %and.3, %and.4
|
|
%and.5 = and i32 %iv, 254
|
|
%shl.3 = shl i32 %or.3, 1
|
|
%xor.4 = xor i32 %shl.3, 2
|
|
%or.4 = or i32 %and.5, %xor.4
|
|
%xor.5 = xor i32 %shr.2, %or.4
|
|
%xor.6 = xor i32 %xor.5, %xor.2
|
|
%and.6 = and i32 %xor.6, 255
|
|
%xor.7 = xor i32 %and.6, 1
|
|
%gep = getelementptr i8, ptr %a, i32 %xor.7
|
|
%ld = load i8, ptr %gep, align 1
|
|
%zext = zext i8 %ld to i32
|
|
%gep.2 = getelementptr i32, ptr null, i32 %zext
|
|
store i32 0, ptr %gep.2, align 4
|
|
%iv.next = add i32 %iv, 1
|
|
%cmp = icmp eq i32 %iv.next, 100
|
|
br i1 %cmp, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|