1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
; Check that the default heuristic use the local cse constraints.
; RUN: opt -S -passes=reassociate,early-cse %s -o - | FileCheck %s -check-prefix=LOCAL_CSE
; RUN: opt -S -passes=reassociate,early-cse %s -reassociate-use-cse-local=true -o - | FileCheck %s -check-prefix=LOCAL_CSE
; RUN: opt -S -passes=reassociate,early-cse %s -reassociate-use-cse-local=false -o - | FileCheck %s -check-prefix=CSE
; Check that when we use the heuristic to expose only local (to the first
; encountered block) CSE opportunities, we choose the right sub expression
; to expose.
;
; In these example we have three chains of expressions:
; chain a: inv1, val_bb2, inv2, inv4
; chain b: inv1, val_bb2, inv2, inv5
; chain c: inv1, val_bb2, inv3
;
; The CSE-able pairs with there respective occurrences are:
; inv1, val_bb2: 3
; inv1, inv2: 2
;
; val_bb2 is anchored in bb2 but inv1 and inv2 can start in bb1.
; With the local heuristic we will push inv1, inv2 at the beginning
; of chain_a and chain_b.
; With the non-local heuristic we will push inv1, val_bb2.
define void @chain_spanning_several_blocks(i64 %inv1, i64 %inv2, i64 %inv3, i64 %inv4, i64 %inv5) {
; LOCAL_CSE-LABEL: define void @chain_spanning_several_blocks
; LOCAL_CSE-SAME: (i64 [[INV1:%.*]], i64 [[INV2:%.*]], i64 [[INV3:%.*]], i64 [[INV4:%.*]], i64 [[INV5:%.*]]) {
; LOCAL_CSE-NEXT: bb1:
; LOCAL_CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[INV2]], [[INV1]]
; LOCAL_CSE-NEXT: br label [[BB2:%.*]]
; LOCAL_CSE: bb2:
; LOCAL_CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
; LOCAL_CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV4]]
; LOCAL_CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[VAL_BB2]]
; LOCAL_CSE-NEXT: [[CHAIN_B1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV5]]
; LOCAL_CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_B1]], [[VAL_BB2]]
; LOCAL_CSE-NEXT: [[CHAIN_C0:%.*]] = add nuw nsw i64 [[INV3]], [[INV1]]
; LOCAL_CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_C0]], [[VAL_BB2]]
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
; LOCAL_CSE-NEXT: ret void
;
; CSE-LABEL: define void @chain_spanning_several_blocks
; CSE-SAME: (i64 [[INV1:%.*]], i64 [[INV2:%.*]], i64 [[INV3:%.*]], i64 [[INV4:%.*]], i64 [[INV5:%.*]]) {
; CSE-NEXT: bb1:
; CSE-NEXT: br label [[BB2:%.*]]
; CSE: bb2:
; CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
; CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[VAL_BB2]], [[INV1]]
; CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV2]]
; CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV4]]
; CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV5]]
; CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV3]]
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
; CSE-NEXT: ret void
;
bb1:
%chain_a0 = add nuw nsw i64 %inv1, %inv2
br label %bb2
bb2:
%val_bb2 = call i64 @get_val()
%chain_a1 = add nuw nsw i64 %chain_a0, %val_bb2
%chain_a2 = add nuw nsw i64 %chain_a1, %inv4
%chain_b0 = add nuw nsw i64 %val_bb2, %inv1
%chain_b1 = add nuw nsw i64 %chain_b0, %inv2
%chain_b2 = add nuw nsw i64 %chain_b1, %inv5
%chain_c0 = add nuw nsw i64 %val_bb2, %inv3
%chain_c1 = add nuw nsw i64 %chain_c0, %inv1
call void @keep_alive(i64 %chain_a2)
call void @keep_alive(i64 %chain_b2)
call void @keep_alive(i64 %chain_c1)
ret void
}
; Same as @chain_spanning_several_blocks, but with values that are all anchored
; on the non-entry block.
; I.e., same pair map as previous but with invX_bbY instead of invX.
; Note: Although %inv1_bb0 is anchored in the entry block, it doesn't constrain
; the sub expressions on the entry block because we need to see at least two
; values to be able to form a sub-expression and thus only the second one
; add a constraint.
define void @chain_spanning_several_blocks_no_entry_anchor() {
; LOCAL_CSE-LABEL: define void @chain_spanning_several_blocks_no_entry_anchor() {
; LOCAL_CSE-NEXT: bb0:
; LOCAL_CSE-NEXT: [[INV2_BB0:%.*]] = call i64 @get_val()
; LOCAL_CSE-NEXT: br label [[BB1:%.*]]
; LOCAL_CSE: bb1:
; LOCAL_CSE-NEXT: [[INV1_BB1:%.*]] = call i64 @get_val()
; LOCAL_CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[INV1_BB1]], [[INV2_BB0]]
; LOCAL_CSE-NEXT: br label [[BB2:%.*]]
; LOCAL_CSE: bb2:
; LOCAL_CSE-NEXT: [[INV3_BB2:%.*]] = call i64 @get_val()
; LOCAL_CSE-NEXT: [[INV4_BB2:%.*]] = call i64 @get_val()
; LOCAL_CSE-NEXT: [[INV5_BB2:%.*]] = call i64 @get_val()
; LOCAL_CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
; LOCAL_CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV4_BB2]]
; LOCAL_CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[VAL_BB2]]
; LOCAL_CSE-NEXT: [[CHAIN_B1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV5_BB2]]
; LOCAL_CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_B1]], [[VAL_BB2]]
; LOCAL_CSE-NEXT: [[CHAIN_C0:%.*]] = add nuw nsw i64 [[VAL_BB2]], [[INV1_BB1]]
; LOCAL_CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_C0]], [[INV3_BB2]]
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
; LOCAL_CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
; LOCAL_CSE-NEXT: ret void
;
; CSE-LABEL: define void @chain_spanning_several_blocks_no_entry_anchor() {
; CSE-NEXT: bb0:
; CSE-NEXT: [[INV2_BB0:%.*]] = call i64 @get_val()
; CSE-NEXT: br label [[BB1:%.*]]
; CSE: bb1:
; CSE-NEXT: [[INV1_BB1:%.*]] = call i64 @get_val()
; CSE-NEXT: br label [[BB2:%.*]]
; CSE: bb2:
; CSE-NEXT: [[INV3_BB2:%.*]] = call i64 @get_val()
; CSE-NEXT: [[INV4_BB2:%.*]] = call i64 @get_val()
; CSE-NEXT: [[INV5_BB2:%.*]] = call i64 @get_val()
; CSE-NEXT: [[VAL_BB2:%.*]] = call i64 @get_val()
; CSE-NEXT: [[CHAIN_A0:%.*]] = add nuw nsw i64 [[VAL_BB2]], [[INV1_BB1]]
; CSE-NEXT: [[CHAIN_A1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV2_BB0]]
; CSE-NEXT: [[CHAIN_A2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV4_BB2]]
; CSE-NEXT: [[CHAIN_B2:%.*]] = add nuw nsw i64 [[CHAIN_A1]], [[INV5_BB2]]
; CSE-NEXT: [[CHAIN_C1:%.*]] = add nuw nsw i64 [[CHAIN_A0]], [[INV3_BB2]]
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_A2]])
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_B2]])
; CSE-NEXT: call void @keep_alive(i64 [[CHAIN_C1]])
; CSE-NEXT: ret void
;
bb0:
%inv2_bb0 = call i64 @get_val()
br label %bb1
bb1:
%inv1_bb1 = call i64 @get_val()
%chain_a0 = add nuw nsw i64 %inv1_bb1, %inv2_bb0
br label %bb2
bb2:
%inv3_bb2 = call i64 @get_val()
%inv4_bb2 = call i64 @get_val()
%inv5_bb2 = call i64 @get_val()
%val_bb2 = call i64 @get_val()
%chain_a1 = add nuw nsw i64 %chain_a0, %val_bb2
%chain_a2 = add nuw nsw i64 %chain_a1, %inv4_bb2
%chain_b0 = add nuw nsw i64 %val_bb2, %inv1_bb1
%chain_b1 = add nuw nsw i64 %chain_b0, %inv2_bb0
%chain_b2 = add nuw nsw i64 %chain_b1, %inv5_bb2
%chain_c0 = add nuw nsw i64 %val_bb2, %inv3_bb2
%chain_c1 = add nuw nsw i64 %chain_c0, %inv1_bb1
call void @keep_alive(i64 %chain_a2)
call void @keep_alive(i64 %chain_b2)
call void @keep_alive(i64 %chain_c1)
ret void
}
declare i64 @get_val()
declare void @keep_alive(i64)
|