2 // Verifies that the debugging experience of loops marked optnone is as expected.
5 // UNSUPPORTED: system-windows
6 // UNSUPPORTED: system-darwin
8 // RUN: %clang -std=gnu++11 -O2 -g %s -o %t
9 // RUN: %dexter --fail-lt 1.0 -w \
10 // RUN: --binary %t --debugger 'lldb' -- %s
12 // A simple loop of assignments.
13 // With optimization level > 0 the compiler reorders basic blocks
14 // based on the basic block frequency analysis information.
15 // This also happens with optnone and it shouldn't.
16 // This is not affecting debug info so it is a minor limitation.
17 // Basic block placement based on the block frequency analysis
18 // is normally done to improve i-Cache performances.
19 __attribute__((optnone
)) void simple_memcpy_loop(int *dest
, const int *src
,
21 for (unsigned i
= 0; i
!= nelems
; ++i
)
22 dest
[i
] = src
[i
]; // DexLabel('target_simple_memcpy_loop')
25 // DexLimitSteps('i', 0, 4, 8, on_line=ref('target_simple_memcpy_loop'))
26 // DexExpectWatchValue('nelems', '16', on_line=ref('target_simple_memcpy_loop'))
27 // DexExpectWatchValue('src[i]', '3', '7', '1', on_line=ref('target_simple_memcpy_loop'))
30 // A trivial loop that could be optimized into a builtin memcpy
31 // which is either expanded into a optimal sequence of mov
32 // instructions or directly into a call to memset@plt
33 __attribute__((optnone
)) void trivial_memcpy_loop(int *dest
, const int *src
) {
34 for (unsigned i
= 0; i
!= 16; ++i
)
35 dest
[i
] = src
[i
]; // DexLabel('target_trivial_memcpy_loop')
38 // DexLimitSteps('i', 3, 7, 9, 14, 15, on_line=ref('target_trivial_memcpy_loop'))
39 // DexExpectWatchValue('i', 3, 7, 9, 14, 15, on_line=ref('target_trivial_memcpy_loop'))
40 // DexExpectWatchValue('dest[i-1] == src[i-1]', 'true', on_line=ref('target_trivial_memcpy_loop'))
43 __attribute__((always_inline
)) int foo(int a
) { return a
+ 5; }
45 // A trivial loop of calls to a 'always_inline' function.
46 __attribute__((optnone
)) void nonleaf_function_with_loop(int *dest
,
48 for (unsigned i
= 0; i
!= 16; ++i
)
49 dest
[i
] = foo(src
[i
]); // DexLabel('target_nonleaf_function_with_loop')
52 // DexLimitSteps('i', 1, on_line=ref('target_nonleaf_function_with_loop'))
53 // DexExpectWatchValue('dest[0]', '8', on_line=ref('target_nonleaf_function_with_loop'))
54 // DexExpectWatchValue('dest[1]', '4', on_line=ref('target_nonleaf_function_with_loop'))
55 // DexExpectWatchValue('dest[2]', '5', on_line=ref('target_nonleaf_function_with_loop'))
56 // DexExpectWatchValue('src[0]', '8', on_line=ref('target_nonleaf_function_with_loop'))
57 // DexExpectWatchValue('src[1]', '4', on_line=ref('target_nonleaf_function_with_loop'))
58 // DexExpectWatchValue('src[2]', '5', on_line=ref('target_nonleaf_function_with_loop'))
60 // DexExpectWatchValue('src[1] == dest[1]', 'true', on_line=ref('target_nonleaf_function_with_loop'))
61 // DexExpectWatchValue('src[2] == dest[2]', 'true', on_line=ref('target_nonleaf_function_with_loop'))
64 // This entire function could be optimized into a
65 // simple movl %esi, %eax.
66 // That is because we can compute the loop trip count
67 // knowing that ind-var 'i' can never be negative.
68 __attribute__((optnone
)) int counting_loop(unsigned values
) {
70 while (values
--) // DexLabel('target_counting_loop')
75 // DexLimitSteps('i', 8, 16, on_line=ref('target_counting_loop'))
76 // DexExpectWatchValue('i', 8, 16, on_line=ref('target_counting_loop'))
79 // This loop could be rotated.
93 // the compiler will not try to optimize this function.
94 // However the Machine BB Placement Pass will try
95 // to reorder the basic block that computes the
96 // expression 'count' in order to simplify the control
98 __attribute__((optnone
)) int loop_rotate_test(int *src
, unsigned count
) {
102 result
+= src
[count
- 1]; // DexLabel('target_loop_rotate_test')
105 return result
; // DexLabel('target_loop_rotate_test_ret')
108 // DexLimitSteps('result', 13, on_line=ref('target_loop_rotate_test'))
109 // DexExpectWatchValue('src[count]', 13, on_line=ref('target_loop_rotate_test'))
110 // DexLimitSteps('result', 158, on_line=ref('target_loop_rotate_test_ret'))
111 // DexExpectWatchValue('result', 158, on_line=ref('target_loop_rotate_test_ret'))
114 typedef int *intptr
__attribute__((aligned(16)));
116 // This loop can be vectorized if we enable
117 // the loop vectorizer.
118 __attribute__((optnone
)) void loop_vectorize_test(intptr dest
, intptr src
) {
123 while(count
!= 16) { // DexLabel('target_loop_vectorize_test')
124 tempArray
[count
] = src
[count
];
125 tempArray
[count
+1] = src
[count
+1]; // DexLabel('target_loop_vectorize_test_2')
126 tempArray
[count
+2] = src
[count
+2]; // DexLabel('target_loop_vectorize_test_3')
127 tempArray
[count
+3] = src
[count
+3]; // DexLabel('target_loop_vectorize_test_4')
128 dest
[count
] = tempArray
[count
]; // DexLabel('target_loop_vectorize_test_5')
129 dest
[count
+1] = tempArray
[count
+1]; // DexLabel('target_loop_vectorize_test_6')
130 dest
[count
+2] = tempArray
[count
+2]; // DexLabel('target_loop_vectorize_test_7')
131 dest
[count
+3] = tempArray
[count
+3]; // DexLabel('target_loop_vectorize_test_8')
132 count
+= 4; // DexLabel('target_loop_vectorize_test_9')
136 // DexLimitSteps('count', 4, 8, 12, 16, from_line=ref('target_loop_vectorize_test'), to_line=ref('target_loop_vectorize_test_9'))
137 // DexExpectWatchValue('tempArray[count] == src[count]', 'true', on_line=ref('target_loop_vectorize_test_2'))
138 // DexExpectWatchValue('tempArray[count+1] == src[count+1]', 'true', on_line=ref('target_loop_vectorize_test_3'))
139 // DexExpectWatchValue('tempArray[count+2] == src[count+2]', 'true', on_line=ref('target_loop_vectorize_test_4'))
140 // DexExpectWatchValue('tempArray[count+3] == src[count+3]', 'true', on_line=ref('target_loop_vectorize_test_5'))
141 // DexExpectWatchValue('dest[count] == tempArray[count]', 'true', on_line=ref('target_loop_vectorize_test_6'))
142 // DexExpectWatchValue('dest[count+1] == tempArray[count+1]', 'true', on_line=ref('target_loop_vectorize_test_7'))
143 // DexExpectWatchValue('dest[count+2] == tempArray[count+2]', 'true', on_line=ref('target_loop_vectorize_test_8'))
144 // DexExpectWatchValue('dest[count+3] == tempArray[count+3]', 'true', on_line=ref('target_loop_vectorize_test_9'))
148 int A
[] = {3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
149 int B
[] = {13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
150 int C
[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
152 simple_memcpy_loop(C
, A
, 16);
153 trivial_memcpy_loop(B
, C
);
154 nonleaf_function_with_loop(B
, B
);
155 int count
= counting_loop(16);
156 count
+= loop_rotate_test(B
, 16);
157 loop_vectorize_test(A
, B
);