-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathassume_aligned.html
More file actions
573 lines (493 loc) · 72.8 KB
/
Copy pathassume_aligned.html
File metadata and controls
573 lines (493 loc) · 72.8 KB
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
<!doctype html>
<html class="cpprefjp" lang="ja" itemscope="" itemtype="http://schema.org/WebPage">
<head>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NXNBNVBTJS"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-NXNBNVBTJS');
</script>
<meta charset="UTF-8">
<title>std::assume_aligned - cpprefjp C++日本語リファレンス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="keywords" content="
C++,標準ライブラリ,リファレンス,ドキュメント,STL,std,memory,function,std,cpp20
">
<meta name="title" content="std::assume_aligned - cpprefjp C++日本語リファレンス" />
<meta itemprop="name" content="std::assume_aligned - cpprefjp C++日本語リファレンス" />
<meta property="og:title" content="std::assume_aligned - cpprefjp C++日本語リファレンス" />
<meta property="og:url" content="https://cpprefjp.github.io/reference/memory/assume_aligned.html" />
<meta property="og:site_name" content="cpprefjp - C++日本語リファレンス" />
<meta property="og:type" content="article" />
<meta property="og:description" content="特定のメモリ領域のアライメント情報をプログラマが明示的にコンパイラへ与えコンパイラが最適化のヒントとして活用できるようにする。" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="std::assume_aligned - cpprefjp C++日本語リファレンス" />
<meta name="twitter:url" content="https://cpprefjp.github.io/reference/memory/assume_aligned.html" />
<meta name="twitter:description" content="特定のメモリ領域のアライメント情報をプログラマが明示的にコンパイラへ与えコンパイラが最適化のヒントとして活用できるようにする。" />
<link rel="alternate" type="application/atom+xml" title="Atom" href="https://cpprefjp.github.io/rss.xml" />
<link rel="apple-touch-icon" sizes="180x180" href="../../static/favicons/apple-touch-icon.png?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc">
<link rel="icon" type="image/png" sizes="32x32" href="../../static/favicons/favicon-32x32.png?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc">
<link rel="icon" type="image/png" sizes="16x16" href="../../static/favicons/favicon-16x16.png?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc">
<link rel="manifest" href="../../manifest.json?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc">
<meta name="theme-color" content="#f5f8fc">
<link rel="stylesheet" href="../../static/pygments/default.css?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc">
<!-- <link rel="stylesheet" href="../../static/css/root.css"> -->
<link href="../../static/kunai/css/kunai-stage-0.css?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-1.css?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-2.css?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-3.css?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc" rel="stylesheet">
<script type="text/javascript" src="../../static/kunai/js/kunai-vendor.js?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc"></script>
<script type="text/javascript" src="../../static/kunai/js/kunai.js?cachebust=557cd0469f26f0f797224f46d1b6e764266f07cc"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var kn = new Kunai;
kn.cpprefjp();
});
</script>
</head>
<body>
<header data-kunai-mdinfo="{"meta": {"header": ["memory"], "id-type": ["function"], "namespace": ["std"], "cpp": ["cpp20"]}, "sources": [{"id": "076bb329f51254c56df9159e8f9df88456a5c4ca", "source": "#include <memory>\n#include <new>\n#include <cstdint>\n#include <iostream>\n\n// \u4f8b\u3048\u3070\u7ffb\u8a33\u5358\u4f4d\u304c\u7570\u306a\u308b\u3001\u3042\u308b\u3044\u306f\u4ed6\u4eba\u306e\u4f5c\u6210\u3057\u305f\u4ed5\u69d8\u306f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3067\u308f\u304b\u308b\u304c\n// \u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u306f\u4e0d\u660e\u306a\u5b9f\u884c\u6642\u306b\u30ea\u30f3\u30af\u3059\u308b\u3069\u3053\u304b\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u304c\u3042\u308b\u3068\u3057\u3088\u3046\u3002\nnamespace external_library\n{\n static char* memory_pool = nullptr;\n\n // \u305d\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u4e2d\u3067\u4ed5\u69d8\u4e0a\u306f\u9818\u57df\u5168\u4f53\u3068\u3057\u3066\u306f 16-byte \u30a2\u30e9\u30a4\u30e1\u30f3\u30c8\u3055\u308c\u305f\n // 4 \u3064\u9023\u7d9a\u3057\u305f float \u578b\u306e\u9818\u57df\u3092 return \u3057\u3066\u304f\u308c\u308b\u95a2\u6570\u304c\u3042\u3063\u305f\u3068\u3057\u3088\u3046\u3002\n float* get_data()\n {\n if ( memory_pool == nullptr )\n memory_pool = new char[ 32 ];\n\n static_assert( sizeof( decltype( memory_pool ) ) == 8 );\n\n // \u7279\u306b\u3001\u3053\u306e\u3088\u3046\u306a\u5b9f\u88c5\u3067\u30a2\u30e9\u30a4\u30e1\u30f3\u30c8\u306e\u4ed5\u69d8\u3092\u6e80\u305f\u3057\u3066\u3044\u305f\u5834\u5408\u306b\u306f\n // \u7ffb\u8a33\u5358\u4f4d\u304c\u7570\u306a\u308c\u3070\u3001\u547c\u3073\u51fa\u3057\u5143\u3092\u7ffb\u8a33\u3059\u308b\u30b3\u30f3\u30d1\u30a4\u30e9\u306f\u305d\u308c\u3092\u77e5\u308b\u306e\u306f\u96e3\u3057\u3044\u3002\n auto data = (float*)( ( (std::uint64_t)memory_pool + 0x0f ) >> 4 << 4 );\n\n for ( auto n = 0; n < 4; ++n )\n data[ n ] = n;\n\n return data;\n }\n}\n\nint main()\n{\n // \u3057\u304b\u3057\u3001\u305d\u308c\u3092\u4f7f\u7528\u3059\u308b\u30b3\u30fc\u30c9\u306e\u30b3\u30f3\u30d1\u30a4\u30eb\u6642\u70b9\u3067\u306f\u3001\n // \u30b3\u30f3\u30d1\u30a4\u30e9\u306f\u5916\u90e8\u30e9\u30a4\u30d6\u30e9\u30ea\u306b\u3088\u3063\u3066\u78ba\u4fdd\u3055\u308c\u308b\u30e1\u30e2\u30ea\u9818\u57df\u304c\n // \u30a2\u30e9\u30a4\u30e1\u30f3\u30c8\u3055\u308c\u3066\u3044\u308b\u4e8b\u306f\u308f\u304b\u3089\u306a\u3044\u3068\u3057\u3088\u3046\u3002\n auto data = external_library::get_data();\n\n // \u305d\u3053\u3067\u3001 assume_aligned() \u3092\u4f7f\u3044\u3001\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3067\u30d7\u30ed\u30b0\u30e9\u30de\u304c\u660e\u793a\u7684\u306b\n // \u7279\u5b9a\u306e\u30e1\u30e2\u30ea\u9818\u57df\u306e\u30a2\u30e9\u30a4\u30e1\u30f3\u30c8\u3092\u30b3\u30f3\u30d1\u30a4\u30e9\u3078\u4f1d\u3048\u308b\u3002\n auto aligned_data = std::assume_aligned< 16 >( data );\n\n // \u30b3\u30f3\u30d1\u30a4\u30e9\u304c\u5341\u5206\u306b\u8ce2\u304f\u6700\u9069\u5316\u3067\u304d\u308b\u306a\u3089\u3070\u3001\n // assume_aligned() \u306e\u30d2\u30f3\u30c8\u4ed8\u3051\u306b\u3088\u308a\u6b21\u306e\u30b3\u30fc\u30c9\u306f\n // 16-byte \u30a2\u30e9\u30a4\u30e1\u30f3\u30c8\u3055\u308c\u305f\u9023\u7d9a\u3057\u305f4\u3064\u306e float \u9818\u57df\u3068\u3057\u3066\u3001\n // \u4f8b\u3048\u3070 SSE \u547d\u4ee4\u3092\u7528\u3044\u305f\u6700\u9069\u5316\u306b\u3088\u308a movaps \u3068 mulps \u547d\u4ee4\u306b\u3088\u308a\n // \u30eb\u30fc\u30d7\u3082\u6392\u9664\u3057\u305f\u5358\u7d14\u3067\u9ad8\u901f\u306a\u6a5f\u68b0\u8a9e\u3092\u751f\u6210\u3057\u3066\u304f\u308c\u308b\u53ef\u80fd\u6027\u304c\u3042\u308b\u3002\n // \uff08 assume_aligned() \u306f\u30d2\u30f3\u30c8\u4ed8\u3051\u3067\u3057\u304b\u306a\u3044\u306e\u3067\u3001\u3069\u3053\u307e\u3067\u30d2\u30f3\u30c8\u3092\u6d3b\u304b\u3057\u3066\u304f\u308c\u308b\u304b\u306f\n // \u30b3\u30f3\u30d1\u30a4\u30e9\u306b\u3088\u3063\u3066\u7d50\u679c\u306f\u7570\u306a\u308b\u3057\u3001\u307e\u3063\u305f\u304f\u6700\u9069\u5316\u306b\u5f79\u7acb\u3066\u3066\u304f\u308c\u306a\u3044\u30b3\u30f3\u30d1\u30a4\u30e9\u3082\u3042\u308b\u304b\u3082\u3057\u308c\u306a\u3044\u3002 \uff09\n for ( auto n = 0; n < 4; ++n )\n aligned_data[ n ] *= aligned_data[ n ];\n\n // \uff08\u5b9f\u884c\u7d50\u679c\u304c\u898b\u308c\u306a\u3044\u3068\u5bc2\u3057\u3044\u306e\u3067\u4ed8\u3051\u305f\u304c\u3001 assume_aligned() \u306e\u4f8b\u3068\u3057\u3066\u306f\u3053\u306e\u90e8\u5206\u306b\u610f\u5473\u306f\u306a\u3044\u3002\uff09\n for ( auto n = 0; n < 4; ++n )\n std::cout << \"data[ \" << n << \" ] = \" << data[ n ] << '\\n';\n}\n"}, {"id": "be0b7a9a66377d0df6e5c06e9fcaff41056a44ff", "source": "#include <memory>\n#include <xmmintrin.h>\n#include <numeric>\n#include <iostream>\n\n//#define MEMORY_ALLOCATE_ABNORMAL_ALIGNMENT\n//#define ASSUME_ALIGN_CPP20\n//#define ASSUME_ALIGN_GCC_OR_CLANG\n//#define ASSUME_ALIGN_ICC\n\ntemplate <typename T, std::size_t size, std::size_t alignment>\nstruct alignas(alignment) aligned_pack\n{ T data[size]; };\n\nusing SSE_SINGLE_TYPE = float;\nconstexpr auto SSE_SINGLE_PACKING = 4;\nconstexpr auto SSE_ALIGNMENT = 16;\n\nusing f32x4 = \n aligned_pack\n < SSE_SINGLE_TYPE\n , SSE_SINGLE_PACKING\n , SSE_ALIGNMENT\n >;\n\nint main()\n{\n constexpr auto N = 256;\n\n#ifdef MEMORY_ALLOCATE_ABNORMAL_ALIGNMENT\n // SSE_ALIGNMENT \u30a2\u30e9\u30a4\u30e1\u30f3\u30c8\u3067 float \u8981\u7d20\u3092 N + 1 \u500b\u306e\u914d\u5217\u3092\u78ba\u4fdd\u3059\u308b\u304c\u3001\n // \u308f\u3056\u3068 1-byte \u3060\u3051\u30a2\u30c9\u30ec\u30b9\u3092\u305a\u3089\u3057\u305f\u5b9f\u9a13\u7528\u306e data \u9818\u57df\u3092\u5b9a\u7fa9\n alignas( SSE_ALIGNMENT ) f32x4 memory_pool[ N + 1 ];\n f32x4* packs = (f32x4*)( (char*)&memory_pool[ 0 ] + 1 );\n#else\n // \u7d20\u76f4\u306b SSE_ALIGNMENT \u30a2\u30e9\u30a4\u30e1\u30f3\u30c8\u3067 float \u8981\u7d20\u3092 N \u500b\u306e\u914d\u5217\u3092\u5b9a\u7fa9\n alignas( SSE_ALIGNMENT ) f32x4 packs[ N ];\n#endif\n\n std::fill( &packs[ 0 ].data[ 0 ], &packs[ N ].data[ 0 ], 1.0f );\n\n for ( auto n = 0; n < N; ++n )\n {\n auto& pack = packs[ n ];\n auto xmm =\n#ifdef ASSUME_ALIGN_CPP20\n _mm_load_ps( std::assume_aligned< SSE_ALIGNMENT >( pack.data ) );\n#elif defined( ASSUME_ALIGN_GCC_OR_CLANG )\n _mm_load_ps( (float*)__builtin_assume_aligned( pack.data, SSE_ALIGNMENT ) );\n#elif defined( ASSUME_ALIGN_ICC )\n _mm_load_ups( (float*)__assume_aligned( pack.data, SSE_ALIGNMENT ) );\n#else\n _mm_load_ps( pack.data );\n#endif\n\n xmm = _mm_add_ps( xmm, xmm );\n _mm_store_ps( pack.data, xmm );\n }\n\n std::cout << std::accumulate( &packs[ 0 ].data[ 0 ], &packs[ N ].data[ 0 ], 0.0f );\n}\n"}], "page_id": ["reference", "memory", "assume_aligned"]}">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../index.html">
<div class="title-wrapper clearfix">
<div class="title">cpprefjp - C++日本語リファレンス</div>
</div>
</a>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li>
<div class="google-search">
<script>
(function() {
var cx = '013316413321391058734:ji_u66hl7hq';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
<div class="gcse-search"></div>
</div>
</li>
<li>
<a href="https://github.com/cpprefjp/site">GitHub Project</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main id="main" role="main">
<div class="container-fluid">
<div class="row">
<div class="col-sm-9 col-sm-push-3" itemscope itemtype="http://schema.org/Article">
<div class="row">
<div class="col-sm-12 google-search-result">
<gcse:searchresults></gcse:searchresults>
</div>
</div>
<div class="row">
<div class="col-sm-12 content-header">
<ol class="breadcrumb">
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../index.html" itemprop="url">
<i class="fa fa-fw fa-home"></i>
</a>
</span>
</li>
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../reference.html" itemprop="url">
<span itemprop="name">リファレンス</span>
</a>
</span>
</li>
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../reference/memory.html" itemprop="url">
<span itemprop="name">memory</span>
</a>
</span>
</li>
<li class="active" itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<span itemprop="name">assume_aligned</span>
</span>
</li>
</ol>
<div class="crsearch"></div>
</div>
</div>
<div class="row">
<div class="col-sm-12 edit-button">
<p class="text-right"><small>
最終更新日時:
<time itemprop="datePublished" class="js-local-time"
datetime="2025-07-09T00:33:39+09:00">
2025年07月09日 00時33分39秒 (JST)
</time>
<br/>
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
<span itemprop="name">Akira Takahashi</span>
</span>
が更新
</small></p>
<script>
(function () {
// 最終更新日時を閲覧者のローカルタイムゾーンで表示し直す (issue #53 の正規化)。
// JS が無効な環境ではサーバ生成の JST 表記がそのまま残る。
function pad(n) { return (n < 10 ? '0' : '') + n; }
var els = document.querySelectorAll('time.js-local-time[datetime]');
for (var i = 0; i < els.length; i++) {
var el = els[i];
var d = new Date(el.getAttribute('datetime'));
if (isNaN(d.getTime())) { continue; }
var tz = '';
try {
var parts = new Intl.DateTimeFormat(undefined, { timeZoneName: 'short' }).formatToParts(d);
for (var j = 0; j < parts.length; j++) {
if (parts[j].type === 'timeZoneName') { tz = parts[j].value; break; }
}
} catch (e) {}
el.textContent = d.getFullYear() + '年' + pad(d.getMonth() + 1) + '月' + pad(d.getDate()) + '日 '
+ pad(d.getHours()) + '時' + pad(d.getMinutes()) + '分' + pad(d.getSeconds()) + '秒'
+ (tz ? ' (' + tz + ')' : '');
}
})();
</script>
<p class="text-right">
<a class="history" target="_blank" href="https://github.com/cpprefjp/site/commits/master/reference/memory/assume_aligned.md">
<span class="fa fa-fw fa-clock-o fa-flip-horizontal"></span>履歴
</a>
<a class="edit" target="_blank" href="https://github.com/cpprefjp/site/edit/master/reference/memory/assume_aligned.md">
<span class="fa fa-fw fa-pencil"></span>編集
</a>
</p>
</div>
</div>
<div class="row">
<div class="col-sm-12 content-body">
<div class="identifier-type">function</div><div class="header"><memory></div><h1 itemprop="name"><span class="namespace" title="namespace std">std::</span><span class="token">assume_aligned</span><span class="cpp cpp20" title="C++20で追加">(C++20)</span></h1>
<div itemprop="articleBody"><p><div class="codehilite"><pre><span></span><code><span class="k">namespace</span><span class="w"> </span><span class="nn">std</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="n"><a href="../cstddef/size_t.html">std::size_t</a></span><span class="w"> </span><span class="n">N</span><span class="p">,</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="w"> </span><span class="p">[[</span><span class="n">nodiscard</span><span class="p">]]</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">assume_aligned</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">ptr</span><span class="p">);</span><span class="w"> </span><span class="c1">// (1) C++20</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="n"><a href="../cstddef/size_t.html">std::size_t</a></span><span class="w"> </span><span class="n">N</span><span class="p">,</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">assume_aligned</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">ptr</span><span class="p">);</span><span class="w"> </span><span class="c1">// (1) C++26</span>
<span class="p">}</span>
</code></pre></div>
</p>
<h2>概要</h2>
<p>特定のメモリ領域のアライメント情報をプログラマが明示的にコンパイラへ与えコンパイラが最適化のヒントとして活用できるようにする。</p>
<p>より具体的には連続したメモリ領域へのアクセスにおけるキャッシュ最適化や SIMD 命令を使用した処理速度やフットプリントの最適化の可能性に対し、メモリ領域のアライメントをプログラマによって明示的にコンパイラへ与える事で、より良好な最適化をコンパイラが選択し得る可能性を与える。</p>
<p>(但し、本機能の使用により実際にどのような最適化にどの程度の効果が得られるかは処理系や最適化オプションにより異なる。プログラマが期待し得た最適化を必ずしもコンパイラが行えるようになるとは限らない。)</p>
<h2>効果</h2>
<p>本機能の効果はコンパイラの対象メモリ領域に対する機械語の生成と最適化の選択として現れる。適切に使用した場合はプログラムの実行結果そのものについて効果を持つ事はないが、より高度な最適化が施され、生成されるプログラムの動作速度やフットプリントに良好な効果を及ぼす可能性が得られる。但し、例で示す様に不適切な使用があった場合にはコンパイラが不正な機械語の選択を行い実行不能なプログラムを生成する可能性も生じる。</p>
<h2><a class="cpprefjp-defined-word" data-desc="関数呼び出し式の評価結果となるオブジェクト・値">戻り値</a></h2>
<p>パラメータ <code>ptr</code> がそのまま返る。(この関数の意義については「効果」を参照されたい。)</p>
<h2>備考</h2>
<p>この機能によって引数または<a class="cpprefjp-defined-word" data-desc="関数呼び出し式の評価結果となるオブジェクト・値">戻り値</a>として得られるメモリ領域が変化する事はない。アライメント不定のメモリ領域を本機能へ渡してもアライメントされたメモリ領域を得られるわけではない。アライメントされたメモリ領域を得たい場合には、先ず <code>alignas</code> を参照すると良い。</p>
<h2>例</h2>
<p>はじめに、ごく単純な使用例のみを示す。但し、 <code>assume_aligned()</code> の効果はソースコード上の記述と実行結果だけでは分かりにくいため、後にもう1つ、 <code>assume_aligned()</code> の効果をより具体的に解説する例も示す。</p>
<h3>例1: ごく単純な使用例</h3>
<p><div class="yata" id="076bb329f51254c56df9159e8f9df88456a5c4ca"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../memory.html"><memory></a></span>
<span class="cp">#include <a href="../new.html"><new></a></span>
<span class="cp">#include <a href="../cstdint.html"><cstdint></a></span>
<span class="cp">#include <a href="../iostream.html"><iostream></a></span>
<span class="c1">// 例えば翻訳単位が異なる、あるいは他人の作成した仕様はドキュメントでわかるが</span>
<span class="c1">// ソースコードは不明な実行時にリンクするどこかのライブラリがあるとしよう。</span>
<span class="k">namespace</span><span class="w"> </span><span class="nn">external_library</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">memory_pool</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">nullptr</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// そのライブラリの中で仕様上は領域全体としては 16-byte アライメントされた</span>
<span class="w"> </span><span class="c1">// 4 つ連続した float 型の領域を return してくれる関数があったとしよう。</span>
<span class="w"> </span><span class="kt">float</span><span class="o">*</span><span class="w"> </span><span class="nf">get_data</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">memory_pool</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">nullptr</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="n">memory_pool</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">char</span><span class="p">[</span><span class="w"> </span><span class="mi">32</span><span class="w"> </span><span class="p">];</span>
<span class="w"> </span><span class="k">static_assert</span><span class="p">(</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="w"> </span><span class="k">decltype</span><span class="p">(</span><span class="w"> </span><span class="n">memory_pool</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="c1">// 特に、このような実装でアライメントの仕様を満たしていた場合には</span>
<span class="w"> </span><span class="c1">// 翻訳単位が異なれば、呼び出し元を翻訳するコンパイラはそれを知るのは難しい。</span>
<span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="o">*</span><span class="p">)(</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="p">(</span><span class="n"><a href="../cstdint/uint64_t.html">std::uint64_t</a></span><span class="p">)</span><span class="n">memory_pool</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mh">0x0f</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">4</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">n</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="n">data</span><span class="p">[</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">data</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="c1">// しかし、それを使用するコードのコンパイル時点では、</span>
<span class="w"> </span><span class="c1">// コンパイラは外部ライブラリによって確保されるメモリ領域が</span>
<span class="w"> </span><span class="c1">// アライメントされている事はわからないとしよう。</span>
<span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">external_library</span><span class="o">::</span><span class="n">get_data</span><span class="p">();</span>
<span class="w"> </span><span class="c1">// そこで、 assume_aligned() を使い、ソースコードでプログラマが明示的に</span>
<span class="w"> </span><span class="c1">// 特定のメモリ領域のアライメントをコンパイラへ伝える。</span>
<span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">aligned_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><span style="color:#ff0000">std::assume_aligned</span></span><span class="o"><</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="o">></span><span class="p">(</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="c1">// コンパイラが十分に賢く最適化できるならば、</span>
<span class="w"> </span><span class="c1">// assume_aligned() のヒント付けにより次のコードは</span>
<span class="w"> </span><span class="c1">// 16-byte アライメントされた連続した4つの float 領域として、</span>
<span class="w"> </span><span class="c1">// 例えば SSE 命令を用いた最適化により movaps と mulps 命令により</span>
<span class="w"> </span><span class="c1">// ループも排除した単純で高速な機械語を生成してくれる可能性がある。</span>
<span class="w"> </span><span class="c1">// ( assume_aligned() はヒント付けでしかないので、どこまでヒントを活かしてくれるかは</span>
<span class="w"> </span><span class="c1">// コンパイラによって結果は異なるし、まったく最適化に役立ててくれないコンパイラもあるかもしれない。 )</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">4</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">n</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="n">aligned_data</span><span class="p">[</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="o">*=</span><span class="w"> </span><span class="n">aligned_data</span><span class="p">[</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">];</span>
<span class="w"> </span><span class="c1">// (実行結果が見れないと寂しいので付けたが、 assume_aligned() の例としてはこの部分に意味はない。)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">4</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">n</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="n"><a href="../iostream/cout.html">std::cout</a></span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"data[ "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">" ] = "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">data</span><span class="p">[</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h4>出力</h4>
<p>次に示す出力は期待動作を示すものではあるが、残念ながら <code>assume_aligned()</code> の効果については読み取れない。</p>
<p><pre><code>data[ 0 ] = 0
data[ 1 ] = 1
data[ 2 ] = 4
data[ 3 ] = 9
</code></pre></p>
<h3>例2: 効果をより具体的に解説する例</h3>
<p>このソースコードでは x86 系の近年の CPU では一般的に使用可能となっている SSE 命令セットから <code>float</code> を 4 つ同時に扱う命令が使用可能な環境を想定し、</p>
<ol>
<li>コンパイラが操作対象のメモリ領域のアライメントに基づく最適化の可否を十分に判断できる場合、</li>
<li>十分には判断できない場合、</li>
<li>十分には判断できなくともソースコード上に <code>assume_aligned()</code> (または相当するコンパイラの独自実装機能)を用いてプログラマが明示的にアライメントをコンパイラへ指示した場合</li>
</ol>
<p>について <code>#define</code> により選択的にコンパイルできるようにした。</p>
<p>この例2ではソースコードの後に通常の「出力」に代えて、 <code>assume_aligned()</code> の効果を確認するため「逆アセンブル」の一部を示す。</p>
<p><div class="yata" id="be0b7a9a66377d0df6e5c06e9fcaff41056a44ff"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../memory.html"><memory></a></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><xmmintrin.h></span>
<span class="cp">#include <a href="../numeric.html"><numeric></a></span>
<span class="cp">#include <a href="../iostream.html"><iostream></a></span>
<span class="c1">//#define MEMORY_ALLOCATE_ABNORMAL_ALIGNMENT</span>
<span class="c1">//#define ASSUME_ALIGN_CPP20</span>
<span class="c1">//#define ASSUME_ALIGN_GCC_OR_CLANG</span>
<span class="c1">//#define ASSUME_ALIGN_ICC</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../cstddef/size_t.html">std::size_t</a></span><span class="w"> </span><span class="n">size</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../cstddef/size_t.html">std::size_t</a></span><span class="w"> </span><span class="n">alignment</span><span class="o">></span>
<span class="k">struct</span><span class="w"> </span><span class="nc">alignas</span><span class="p">(</span><span class="n">alignment</span><span class="p">)</span><span class="w"> </span><span class="n">aligned_pack</span>
<span class="p">{</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">data</span><span class="p">[</span><span class="n">size</span><span class="p">];</span><span class="w"> </span><span class="p">};</span>
<span class="k">using</span><span class="w"> </span><span class="n">SSE_SINGLE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">float</span><span class="p">;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">SSE_SINGLE_PACKING</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">4</span><span class="p">;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">SSE_ALIGNMENT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">16</span><span class="p">;</span>
<span class="k">using</span><span class="w"> </span><span class="n">f32x4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>
<span class="w"> </span><span class="n">aligned_pack</span>
<span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">SSE_SINGLE_TYPE</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">SSE_SINGLE_PACKING</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">SSE_ALIGNMENT</span>
<span class="w"> </span><span class="o">></span><span class="p">;</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">256</span><span class="p">;</span>
<span class="cp">#ifdef MEMORY_ALLOCATE_ABNORMAL_ALIGNMENT</span>
<span class="w"> </span><span class="c1">// SSE_ALIGNMENT アライメントで float 要素を N + 1 個の配列を確保するが、</span>
<span class="w"> </span><span class="c1">// わざと 1-byte だけアドレスをずらした実験用の data 領域を定義</span>
<span class="w"> </span><span class="k">alignas</span><span class="p">(</span><span class="w"> </span><span class="n">SSE_ALIGNMENT</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="n">f32x4</span><span class="w"> </span><span class="n">memory_pool</span><span class="p">[</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">];</span>
<span class="w"> </span><span class="n">f32x4</span><span class="o">*</span><span class="w"> </span><span class="n">packs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">f32x4</span><span class="o">*</span><span class="p">)(</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">memory_pool</span><span class="p">[</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">);</span>
<span class="cp">#else</span>
<span class="w"> </span><span class="c1">// 素直に SSE_ALIGNMENT アライメントで float 要素を N 個の配列を定義</span>
<span class="w"> </span><span class="k">alignas</span><span class="p">(</span><span class="w"> </span><span class="n">SSE_ALIGNMENT</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="n">f32x4</span><span class="w"> </span><span class="n">packs</span><span class="p">[</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="p">];</span>
<span class="cp">#endif</span>
<span class="w"> </span><span class="n"><a href="../algorithm/fill.html">std::fill</a></span><span class="p">(</span><span class="w"> </span><span class="o">&</span><span class="n">packs</span><span class="p">[</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">].</span><span class="n">data</span><span class="p">[</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">],</span><span class="w"> </span><span class="o">&</span><span class="n">packs</span><span class="p">[</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="p">].</span><span class="n">data</span><span class="p">[</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">],</span><span class="w"> </span><span class="mf">1.0f</span><span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">N</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">n</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">auto</span><span class="o">&</span><span class="w"> </span><span class="n">pack</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">packs</span><span class="p">[</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">];</span>
<span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">xmm</span><span class="w"> </span><span class="o">=</span>
<span class="cp">#ifdef ASSUME_ALIGN_CPP20</span>
<span class="w"> </span><span class="n">_mm_load_ps</span><span class="p">(</span><span class="w"> </span><span class="n"><span style="color:#ff0000">std::assume_aligned</span></span><span class="o"><</span><span class="w"> </span><span class="n">SSE_ALIGNMENT</span><span class="w"> </span><span class="o">></span><span class="p">(</span><span class="w"> </span><span class="n">pack</span><span class="p">.</span><span class="n">data</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">);</span>
<span class="cp">#elif defined( ASSUME_ALIGN_GCC_OR_CLANG )</span>
<span class="w"> </span><span class="n">_mm_load_ps</span><span class="p">(</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="o">*</span><span class="p">)</span><span class="n">__builtin_assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">pack</span><span class="p">.</span><span class="n">data</span><span class="p">,</span><span class="w"> </span><span class="n">SSE_ALIGNMENT</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">);</span>
<span class="cp">#elif defined( ASSUME_ALIGN_ICC )</span>
<span class="w"> </span><span class="n">_mm_load_ups</span><span class="p">(</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="o">*</span><span class="p">)</span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">pack</span><span class="p">.</span><span class="n">data</span><span class="p">,</span><span class="w"> </span><span class="n">SSE_ALIGNMENT</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">);</span>
<span class="cp">#else</span>
<span class="w"> </span><span class="n">_mm_load_ps</span><span class="p">(</span><span class="w"> </span><span class="n">pack</span><span class="p">.</span><span class="n">data</span><span class="w"> </span><span class="p">);</span>
<span class="cp">#endif</span>
<span class="w"> </span><span class="n">xmm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">_mm_add_ps</span><span class="p">(</span><span class="w"> </span><span class="n">xmm</span><span class="p">,</span><span class="w"> </span><span class="n">xmm</span><span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="n">_mm_store_ps</span><span class="p">(</span><span class="w"> </span><span class="n">pack</span><span class="p">.</span><span class="n">data</span><span class="p">,</span><span class="w"> </span><span class="n">xmm</span><span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n"><a href="../iostream/cout.html">std::cout</a></span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n"><a href="../numeric/accumulate.html">std::accumulate</a></span><span class="p">(</span><span class="w"> </span><span class="o">&</span><span class="n">packs</span><span class="p">[</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">].</span><span class="n">data</span><span class="p">[</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">],</span><span class="w"> </span><span class="o">&</span><span class="n">packs</span><span class="p">[</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="p">].</span><span class="n">data</span><span class="p">[</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">],</span><span class="w"> </span><span class="mf">0.0f</span><span class="w"> </span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h3>逆アセンブル</h3>
<p>執筆現在は正式にリリースされた <code>GCC</code>, <code>Clang</code>, <code>ICC</code>, <code>MSVC++</code> などの主要なツールチェインではまだ <code>assume_aligned()</code> の正式なサポートは未完了のため <code>assume_aligned()</code> に代えて <code>GCC</code> および <code>Clang</code> において等価な挙動を示す独自拡張 <code>__builtin_assume_aligned()</code> を用いた場合にコンパイラが生成するコードの最適化効果を <code>GCC-8.3</code>, <code>-O2</code> での実行結果を元に示す。</p>
<h4>2.a. いずれの <code>#define</code> も使用しなかった場合</h4>
<p>この場合、コンパイラは <code>packs</code> が <code>alignas</code> により 16-byte アライメントを指示された事を知っている。このため、<code>_mm_load_ps</code> の部分は <code>.L3</code> ラベルのすぐ後で <code>movaps</code> として現れている。 <code>_mm_load_ps</code> は仕様上の直接の対応としては <code>movaps</code> だが、実際はコンパイラによって <code>movups</code> が適切と判断され使用される場合もある。また、 <code>_mm_loadu_ps</code> をコードしていた場合でも <code>movups</code> ではなく <code>movaps</code> へ最適化される場合もある。</p>
<p>つまり、この場合の逆アセンブルからは <code>alignas</code> により 16-byte アライメントで <code>packs</code> のメモリ領域が確保されているから、 XMM レジスタへの読み出し命令はアライメント不明でも使用可能な代わりに僅かに速度的に不利となる可能性のある <code>movups</code> ではなく 16-byte アライメントされたメモリ領域を前提とする代わりに僅かに速度的に有利となる可能性のある <code>movaps</code> が採用される状態となっている事が分かる。</p>
<p><div class="codehilite"><pre><span></span><code><span class="nl">main:</span>
<span class="w"> </span><span class="nf">sub</span><span class="w"> </span><span class="no">rsp</span><span class="p">,</span><span class="w"> </span><span class="mi">4104</span>
<span class="w"> </span><span class="nf">movss</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">DWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="no">.LC1</span><span class="p">[</span><span class="no">rip</span><span class="p">]</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="no">rsp</span>
<span class="nl">.L2:</span>
<span class="w"> </span><span class="nf">movss</span><span class="w"> </span><span class="no">DWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax</span><span class="p">],</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">lea</span><span class="w"> </span><span class="no">rcx</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="no">rsp</span><span class="err">+</span><span class="mi">4096</span><span class="p">]</span>
<span class="w"> </span><span class="nf">add</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span>
<span class="w"> </span><span class="nf">cmp</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="no">rcx</span>
<span class="w"> </span><span class="nf">jne</span><span class="w"> </span><span class="no">.L2</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="no">rsp</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">rdx</span><span class="p">,</span><span class="w"> </span><span class="no">rcx</span>
<span class="nl">.L3:</span>
<span class="w"> </span><span class="nf">movaps</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">XMMWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax</span><span class="p">]</span>
<span class="w"> </span><span class="nf">add</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="mi">16</span>
<span class="w"> </span><span class="nf">addps</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">movaps</span><span class="w"> </span><span class="no">XMMWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax-16</span><span class="p">],</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">cmp</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="no">rdx</span>
<span class="w"> </span><span class="nf">jne</span><span class="w"> </span><span class="no">.L3</span>
<span class="w"> </span><span class="nf">pxor</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="no">rsp</span>
<span class="nl">.L4:</span>
<span class="w"> </span><span class="nf">addss</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">DWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax</span><span class="p">]</span>
<span class="w"> </span><span class="nf">lea</span><span class="w"> </span><span class="no">rsi</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="no">rsp</span><span class="err">+</span><span class="mi">4096</span><span class="p">]</span>
<span class="w"> </span><span class="nf">add</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span>
<span class="w"> </span><span class="nf">cmp</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="no">rsi</span>
<span class="w"> </span><span class="nf">jne</span><span class="w"> </span><span class="no">.L4</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">edi</span><span class="p">,</span><span class="w"> </span><span class="no">OFFSET</span><span class="w"> </span><span class="no">FLAT</span><span class="p">:</span><span class="no">_ZSt4cout</span>
<span class="w"> </span><span class="nf">cvtss2sd</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">call</span><span class="w"> </span><span class="no"><a href="../ostream/basic_ostream.html">std::basic_ostream</a></span><span class="err"><</span><span class="no">char</span><span class="p">,</span><span class="w"> </span><span class="no"><a href="../string/char_traits.html">std::char_traits</a></span><span class="err"><</span><span class="no">char</span><span class="err">></span><span class="w"> </span><span class="err">>&</span><span class="w"> </span><span class="no"><a href="../ostream/basic_ostream.html">std::basic_ostream</a></span><span class="err"><</span><span class="no">char</span><span class="p">,</span><span class="w"> </span><span class="no"><a href="../string/char_traits.html">std::char_traits</a></span><span class="err"><</span><span class="no">char</span><span class="err">></span><span class="w"> </span><span class="err">></span><span class="p">::</span><span class="no">_M_insert</span><span class="err"><</span><span class="no">double</span><span class="err">></span><span class="p">(</span><span class="no">double</span><span class="p">)</span>
<span class="w"> </span><span class="nf">xor</span><span class="w"> </span><span class="no">eax</span><span class="p">,</span><span class="w"> </span><span class="no">eax</span>
<span class="w"> </span><span class="nf">add</span><span class="w"> </span><span class="no">rsp</span><span class="p">,</span><span class="w"> </span><span class="mi">4104</span>
<span class="w"> </span><span class="nf">ret</span>
<span class="nl">_GLOBAL__sub_I_main:</span>
<span class="w"> </span><span class="nf">sub</span><span class="w"> </span><span class="no">rsp</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">edi</span><span class="p">,</span><span class="w"> </span><span class="no">OFFSET</span><span class="w"> </span><span class="no">FLAT</span><span class="p">:</span><span class="no">_ZStL8__ioinit</span>
<span class="w"> </span><span class="nf">call</span><span class="w"> </span><span class="no">std</span><span class="p">::</span><span class="no">ios_base</span><span class="p">::</span><span class="no">Init</span><span class="p">::</span><span class="no">Init</span><span class="p">()</span><span class="w"> </span><span class="p">[</span><span class="no">complete</span><span class="w"> </span><span class="no">object</span><span class="w"> </span><span class="no">constructor</span><span class="p">]</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">edx</span><span class="p">,</span><span class="w"> </span><span class="no">OFFSET</span><span class="w"> </span><span class="no">FLAT</span><span class="p">:</span><span class="no">__dso_handle</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">esi</span><span class="p">,</span><span class="w"> </span><span class="no">OFFSET</span><span class="w"> </span><span class="no">FLAT</span><span class="p">:</span><span class="no">_ZStL8__ioinit</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">edi</span><span class="p">,</span><span class="w"> </span><span class="no">OFFSET</span><span class="w"> </span><span class="no">FLAT</span><span class="p">:</span><span class="no">_ZNSt8ios_base4InitD1Ev</span>
<span class="w"> </span><span class="nf">add</span><span class="w"> </span><span class="no">rsp</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span>
<span class="w"> </span><span class="nf">jmp</span><span class="w"> </span><span class="no">__cxa_atexit</span>
<span class="nl">.LC1:</span>
<span class="w"> </span><span class="na">.long</span><span class="w"> </span><span class="mi">1065353216</span>
</code></pre></div>
</p>
<h4>2.b. <code>MEMORY_ALLOCATE_ABNORMAL_ALIGNMENT</code> のみ定義した場合</h4>
<p>この場合、 <code>packs</code> は故意に 16-byte アライメントから 1 byte だけずれたメモリ領域となる。すると、 <code>.L3</code> の部分で <code>_mm_load_ps</code> は <code>movups</code> へ翻訳されるようになる。</p>
<p>今回はコンパイラが packs が 16-byte アライメントされていない可能性を検知した事により <code>movaps</code> ではなく <code>movups</code> が安全に採用されている。</p>
<p><div class="codehilite"><pre><span></span><code><span class="nl">.L3:</span>
<span class="w"> </span><span class="nf">movups</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">XMMWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax</span><span class="p">]</span>
<span class="w"> </span><span class="nf">add</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="mi">16</span>
<span class="w"> </span><span class="nf">addps</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">movups</span><span class="w"> </span><span class="no">XMMWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax-16</span><span class="p">],</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">cmp</span><span class="w"> </span><span class="no">rdx</span><span class="p">,</span><span class="w"> </span><span class="no">rax</span>
<span class="w"> </span><span class="nf">jne</span><span class="w"> </span><span class="no">.L3</span>
<span class="w"> </span><span class="nf">pxor</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">lea</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="no">rsp</span><span class="err">+</span><span class="mi">1</span><span class="p">]</span>
<span class="w"> </span><span class="nf">lea</span><span class="w"> </span><span class="no">rdx</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="no">rsp</span><span class="err">+</span><span class="mi">4097</span><span class="p">]</span>
</code></pre></div>
</p>
<h4>2.c. <code>MEMORY_ALLOCATE_ABNORMAL_ALIGNMENT</code> と <code>ASSUME_ALIGN_CPP20</code> または <code>ASSUME_ALIGN_GCC_OR_CLANG</code> を定義した場合</h4>
<p>この場合、 <code>assume_aligned()</code> または <code>__builtin_assume_aligned()</code> によるプログラマからの明示的なヒント付けにより、コンパイラはプログラマからの情報を信じて <code>packs</code> の要素が 16-byte アライメントされたメモリ領域であり、その領域が <code>_mm_load_ps</code> の実引数として渡されていると判断して翻訳を行う。結果、コンパイラは <code>_mm_load_ps</code> を 2.b. の <code>movups</code> ではなく <code>movaps</code> へと翻訳する。</p>
<p><div class="codehilite"><pre><span></span><code><span class="nl">.L3:</span>
<span class="w"> </span><span class="nf">movaps</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">XMMWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax</span><span class="p">]</span>
<span class="w"> </span><span class="nf">add</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="mi">16</span>
<span class="w"> </span><span class="nf">addps</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">movups</span><span class="w"> </span><span class="no">XMMWORD</span><span class="w"> </span><span class="no">PTR</span><span class="w"> </span><span class="p">[</span><span class="no">rax-16</span><span class="p">],</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">cmp</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="no">rdx</span>
<span class="w"> </span><span class="nf">jne</span><span class="w"> </span><span class="no">.L3</span>
<span class="w"> </span><span class="nf">pxor</span><span class="w"> </span><span class="no">xmm0</span><span class="p">,</span><span class="w"> </span><span class="no">xmm0</span>
<span class="w"> </span><span class="nf">lea</span><span class="w"> </span><span class="no">rax</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="no">rsp</span><span class="err">+</span><span class="mi">1</span><span class="p">]</span>
<span class="w"> </span><span class="nf">lea</span><span class="w"> </span><span class="no">rdx</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="no">rsp</span><span class="err">+</span><span class="mi">4097</span><span class="p">]</span>
</code></pre></div>
</p>
<p>なお、この例は逆アセンブルから <code>assume_aligned()</code> の効果を確認するために用意し、その意味ではコンパイラは期待動作してくれるが、この 2.c. から生成される実行バイナリを実行した場合、出力は得られずプログラムは <code>segmentation fault</code> して OS に実行を停止させられてしまう。 16-byte アライメントされたメモリ領域を前提とした <code>movaps</code> を、その前提を確実に満たさないメモリ領域に対して実行する実行プログラムとしては不正な機械語が生成されるため生じる。</p>
<p>例え故意でなくとも <code>assume_aligned()</code> を不適切に用いてしまうと、この様にプログラムは期待動作し得ない実行バイナリを生成してしまう可能性も十分にあるため、使用にあたっては必要性、妥当性について十分に注意すると良い。</p>
<h2>実装例</h2>
<p><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../cstddef.html"><cstddef></a></span>
<span class="cp">#include <a href="../cstdint.html"><cstdint></a></span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n"><a href="../cstddef/size_t.html">std::size_t</a></span><span class="w"> </span><span class="n">N</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="w"> </span><span class="o">></span>
<span class="cp">#if defined( __clang__ ) || defined( __GNUC__ )</span>
<span class="w"> </span><span class="n">__attribute__</span><span class="p">(</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">always_inline</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">)</span>
<span class="cp">#elif defined( _MSC_VER )</span>
<span class="w"> </span><span class="kr">__forceinline</span>
<span class="cp">#endif</span>
<span class="p">[[</span><span class="w"> </span><span class="n">nodiscard</span><span class="w"> </span><span class="p">]]</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="p">)</span>
<span class="p">{</span>
<span class="cp">#if defined( __clang__ ) || ( defined( __GNUC__ ) && !defined( __ICC ) )</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">reinterpret_cast</span><span class="o"><</span><span class="w"> </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="o">></span><span class="p">(</span><span class="w"> </span><span class="n">__builtin_assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">);</span>
<span class="cp">#elif defined(_MSC_VER)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="k">reinterpret_cast</span><span class="o"><</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="kt">uintptr_t</span><span class="w"> </span><span class="o">></span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">ptr</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="kr">__assume</span><span class="p">(</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">);</span>
<span class="cp">#elif defined( __ICC )</span>
<span class="w"> </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">N</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">2</span><span class="p">:</span><span class="w"> </span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">4</span><span class="p">:</span><span class="w"> </span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">8</span><span class="p">:</span><span class="w"> </span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">16</span><span class="p">:</span><span class="w"> </span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">32</span><span class="p">:</span><span class="w"> </span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="mi">32</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">64</span><span class="p">:</span><span class="w"> </span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="mi">64</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="mi">128</span><span class="p">:</span><span class="w"> </span><span class="n">__assume_aligned</span><span class="p">(</span><span class="w"> </span><span class="n">ptr</span><span class="p">,</span><span class="w"> </span><span class="mi">128</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">ptr</span><span class="p">;</span>
<span class="cp">#else</span>
<span class="w"> </span><span class="c1">// Unknown compiler — do nothing</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">ptr</span><span class="p">;</span>
<span class="cp">#endif</span>
<span class="p">}</span>
</code></pre></div>
</p>
<h2>バージョン</h2>
<h3>言語</h3>
<ul>
<li>C++20</li>
</ul>
<h3>処理系</h3>
<ul>
<li><a href="../../implementation.html#clang">Clang</a>: † <span aria-label="検証済" role="img" title="検証済">✅</span></li>
<li><a href="../../implementation.html#gcc">GCC</a>: † ‡ <span aria-label="検証済" role="img" title="検証済">✅</span></li>
<li><a href="../../implementation.html#icc">ICC</a>: † <span aria-label="検証済" role="img" title="検証済">✅</span></li>
<li><a href="../../implementation.html#visual_cpp">Visual C++</a>: † <span aria-label="検証済" role="img" title="検証済">✅</span></li>
</ul>
<p>†2019-04-29 時点で正式リリース版の対応はまだ無い。処理系独自拡張による等価な実装はあり。
‡2019-04-29 時点で <code>GCC-10.0.0 20190426 (experimental)</code> では使用可能を確認。</p>
<p>(本項は初稿時点では処理系の対応がまだ進んでいないため、各処理系の対応情報が明らかとなり次第、記述の更新が求められる。)</p>
<h3>備考</h3>
<p>C++20 から標準で使用可能となる本機能だが、実装例からも分かるように <code>GCC</code> や <code>Clang</code> には等価な独自拡張での実装が以前から存在する。例えば <code>__builtin_assume_aligned</code> は <code>GCC-4.7</code> 以降, <code>Clang-3.6</code> 以降から使用可能だった。</p>
<h2>関連項目</h2>
<ul>
<li><code><a href="../../lang/cpp11/alignas.html">alignas</a></code></li>
<li><code><a href="../../lang/cpp11/alignof.html">alignof</a></code></li>
<li><code><a href="is_sufficiently_aligned.html">is_sufficiently_aligned</a></code></li>
</ul>
<h2>参照</h2>
<ul>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1007r3.pdf" target="_blank">P1007R3 <code>std::assume_aligned</code></a></li>
<li><a href="https://cppmap.github.io/standardization/cpp20/#assume_aligned-p1007r3" target="_blank">cppmap - C++20 の新機能 - ポインタのアライメントを最適化ヒントとしてコンパイラに伝える <code>assume_aligned()</code> 関数 (P1007R3)</a></li>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2422r1.html" target="_blank">P2422R1 Remove <code>nodiscard</code> annotations from the standard library specification</a><ul>
<li>C++26で<code>[[nodiscard]]</code>指定が削除された</li>
</ul>
</li>
</ul></div>
</div>
</div>
</div>
<div id="sidebar" class="col-sm-3 col-sm-pull-9">
</div>
</div>
</div>
</main>
<footer class="footer navbar navbar-default">
<div class="container-fluid">
<p><small>
本サイトの情報は、
<a href="https://creativecommons.org/licenses/by/4.0/deed.ja" rel="nofollow">クリエイティブ・コモンズ 表示 4.0 非移植 ライセンス(CC BY)</a>
の下に提供されています。
</small></p>
</div>
</footer>
</body>
</html>