Subversion Repositories Open64

[/] [trunk/] [osprey/] [be/] [vho/] [vho_lower.cxx] - Blame information for rev 2694

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 marcel
/*
2 2322 dcoakley
 * Copyright (C) 2009 Advanced Micro Devices, Inc.  All Rights Reserved.
3
 */
4
/*
5 749 hucheng
 * Copyright 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
6
 */
7 71 marcel
 
8 749 hucheng
/*
9
 
10 2 marcel
  Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
11
 
12
  This program is free software; you can redistribute it and/or modify it
13
  under the terms of version 2 of the GNU General Public License as
14
  published by the Free Software Foundation.
15
 
16
  This program is distributed in the hope that it would be useful, but
17
  WITHOUT ANY WARRANTY; without even the implied warranty of
18
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
 
20
  Further, this software is distributed without any warranty that it is
21
  free of the rightful claim of any third person regarding infringement
22
  or the like.  Any license provided herein, whether implied or
23
  otherwise, applies only to this software file.  Patent licenses, if
24
  any, provided herein do not apply to combinations of this program with
25
  other software, or any other product whatsoever.
26
 
27
  You should have received a copy of the GNU General Public License along
28
  with this program; if not, write the Free Software Foundation, Inc., 59
29
  Temple Place - Suite 330, Boston MA 02111-1307, USA.
30
 
31
  Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
32
  Mountain View, CA 94043, or:
33
 
34
  http://www.sgi.com
35
 
36
  For further information regarding this notice, see:
37
 
38
  http://oss.sgi.com/projects/GenInfo/NoticeExplan
39
 
40
*/
41
 
42
 
43
//-*-c++-*-
44
 
45 71 marcel
#define __STDC_LIMIT_MACROS
46
#include <stdint.h>
47
 
48 2 marcel
#ifndef FRONT_END
49
 
50
#include "defs.h"
51
#include "config.h"
52
#include "config_opt.h"
53 2694 shenruifen
#include "config_debug.h"
54 2 marcel
#include "mempool.h"
55
#include "wn.h"
56
#include "wn_util.h"
57
#include "opcode.h"
58
#include <stdlib.h>
59
#include "flags.h"
60
#include "pu_info.h"
61
#include "vho_lower.h"
62
#include "f90_lower.h"
63
#include "fb_whirl.h"
64
#include "wn_simp.h"
65
#include "topcode.h"
66
#include "callutil.h"
67
#include "targ_sim.h"
68
#include "cxx_template.h"
69
#include "prompf.h"
70
#include "wb_f90_lower.h"
71
#include "wn_lower.h"
72 2113 laijx
#include "be_util.h"            // For Current_PU_Count
73
#include "glob.h"               // For Show_Progress
74 83 marcel
#ifdef KEY
75
#include "w2op.h"   // For OPCODE_Can_Be_Spculative
76
#endif
77 1950 laijx
#include "config_clist.h"
78 2 marcel
 
79
typedef enum {
80
  ADDRESS_USED,
81
  ADDRESS_PASSED,
82
  ADDRESS_SAVED
83
} ADDRESS_INFO_TYPE;
84
 
85
#endif /* FRONT_END */
86
 
87
#include "tracing.h"
88
#include "ir_reader.h"
89
#include "config_vho.h"
90
#include "targ_const.h"
91 1950 laijx
#include "erbe.h"
92 2 marcel
 
93
#define DO_VHO_LOWERING 1
94
#define IS_POWER_OF_2(x) (((x)!=0) && ((x) & ((x)-1))==0)
95
 
96
#define ST_addr_taken_passed(st)       ST_addr_passed(st)
97
#define Set_ST_addr_taken_passed(st)   Set_ST_addr_passed(st)
98
#define Reset_ST_addr_taken_passed(st) Reset_ST_addr_passed(st)
99
#define ST_addr_taken_saved(st)        ST_addr_saved(st)
100
#define Set_ST_addr_taken_saved(st)    Set_ST_addr_saved(st)
101
#define Reset_ST_addr_taken_saved(st)  Reset_ST_addr_saved(st)
102
 
103
#pragma set woff 1172
104 135 marcel
#ifdef KEY
105
static INT current_pu_id = -1;
106 1411 laijx
static void Misc_Loop_Fusion ( WN * , WN * );
107 135 marcel
#endif
108 2 marcel
 
109
static BOOL
110
VHO_WN_is_zero ( WN * wn )
111
{
112
  return (    (    WN_operator(wn) == OPR_INTCONST
113
                && WN_const_val(wn) == 0 )
114
           || (    WN_operator(wn) == OPR_CONST
115
                && Targ_Is_Zero(STC_val(WN_st(wn))) ) );
116
} /* VHO_WN_is_zero */
117
 
118
 
119
static BOOL
120
VHO_WN_has_side_effects ( WN * wn )
121
{
122
  INT32    nkids;
123
  INT32    i;
124
  OPERATOR wn_operator;
125
  BOOL     has_side_effects;
126
 
127
  wn_operator = WN_operator(wn);
128
  nkids       = WN_kid_count(wn);
129
 
130
  switch ( wn_operator ) {
131
 
132
    case OPR_LDID:
133
 
134
      has_side_effects = TY_is_volatile(WN_ty(wn));
135
      break;
136
 
137
    case OPR_ILOAD:
138
 
139
      has_side_effects =    TY_is_volatile(WN_ty(wn))
140
                         || VHO_WN_has_side_effects ( WN_kid0(wn) );
141
      break;
142
 
143
    default:
144
 
145
      has_side_effects = FALSE;
146
 
147
      for ( i = 0; i < nkids; i++ ) {
148
 
149
        if ( VHO_WN_has_side_effects ( WN_kid(wn,i) ) ) {
150
 
151
          has_side_effects = TRUE;
152
          break;
153
        }
154
      }
155
      break;
156
  }
157
 
158
  return has_side_effects;
159
} /* VHO_WN_has_side_effects */
160
 
161
 
162
typedef struct bool_expr_info_t {
163
  OPCODE opcode;
164
  BOOL   used_true_label;
165
  BOOL   used_false_label;
166
  LABEL_IDX true_label;
167
  LABEL_IDX false_label;
168
} BOOL_INFO;
169
 
170
static WN * vho_lower ( WN * wn, WN * block );
171
static WN * vho_lower_stmt ( WN * stmt, WN * block );
172
static WN * vho_lower_block ( WN * wn );
173 1950 laijx
static WN * vho_lower_expr ( WN * expr, WN * block, BOOL_INFO * bool_info, BOOL is_return=FALSE );
174 2 marcel
 
175
/* Table used to promote integers less than 4 bytes into their
176
 * 4 byte counterparts in order to get the right type for OPCODE_make_op
177
 */
178
 
179
TYPE_ID Promoted_Mtype [MTYPE_LAST + 1] = {
180
  MTYPE_UNKNOWN,  /* MTYPE_UNKNOWN */
181
  MTYPE_UNKNOWN,  /* MTYPE_B */
182
  MTYPE_I4,       /* MTYPE_I1 */
183
  MTYPE_I4,       /* MTYPE_I2 */
184
  MTYPE_I4,       /* MTYPE_I4 */
185
  MTYPE_I8,       /* MTYPE_I8 */
186
  MTYPE_U4,       /* MTYPE_U1 */
187
  MTYPE_U4,       /* MTYPE_U2 */
188
  MTYPE_U4,       /* MTYPE_U4 */
189
  MTYPE_U8,       /* MTYPE_U8 */
190
  MTYPE_F4,       /* MTYPE_F4 */
191
  MTYPE_F8,       /* MTYPE_F8 */
192 515 marcel
  MTYPE_F10,      /* MTYPE_F10 */
193 2 marcel
  MTYPE_UNKNOWN,  /* MTYPE_F16 */
194
  MTYPE_UNKNOWN,  /* MTYPE_STR */
195
  MTYPE_FQ,       /* MTYPE_FQ */
196
  MTYPE_M,        /* MTYPE_M */
197
  MTYPE_C4,       /* MTYPE_C4 */
198
  MTYPE_C8,       /* MTYPE_C8 */
199
  MTYPE_CQ,       /* MTYPE_CQ */
200 1950 laijx
  MTYPE_V,         /* MTYPE_V */
201
#if defined(TARG_IA64)
202 564 marcel
  MTYPE_UNKNOWN,  /* MTYPE_BS */
203
  MTYPE_UNKNOWN,  /* MTYPE_A4 */
204
  MTYPE_UNKNOWN,  /* MTYPE_A8 */
205
  MTYPE_C10,      /* MTYPE_C10 */
206 749 hucheng
#endif
207 2 marcel
};
208
 
209
#ifdef VHO_DEBUG
210
static BOOL      VHO_Switch_Debug = TRUE;
211
static BOOL      VHO_Struct_Debug = TRUE;
212
static char    * VHO_Switch_Format;
213
#endif /* VHO_DEBUG */
214
 
215
static SRCPOS    VHO_Srcpos;
216 2322 dcoakley
static BOOL      VHO_SCL_Debug;             // Debug Structure Copy Lowering
217
static BOOL      VHO_M_Debug_Type_Mismatch;
218 2 marcel
 
219
/* Variables related to handling of switch statements */
220
 
221
INT32   VHO_Switch_Distance = 128;         /* max distance between values    */
222
INT32   VHO_Switch_Default_Label_Count = 16;
223
BOOL    VHO_Give_Preg_Names = FALSE;
224
 
225
static const char * vho_lower_mstore_name    = "__lower_mstore";
226
static const char * vho_lower_cand_cior_name = "__cand_cior";
227
static const char * vho_lower_cselect_name   = "__cselect";
228
static const char * vho_lower_rcomma_name    = "__rcomma";
229
static const char * vho_lower_comma_name     = "__comma";
230
 
231
static TY_IDX vho_u4a1_ty_idx = (TY_IDX) 0;
232
static TY_IDX vho_u8a1_ty_idx = (TY_IDX) 0;
233
 
234
typedef struct switch_case_table_entry_t {
235
  WN    * wn;
236
  INT32   count;
237
  FB_FREQ freq;
238
} VHO_SWITCH_ITEM;
239
 
240
static VHO_SWITCH_ITEM * VHO_Switch_Case_Table; /* table for switch cases    */
241
 
242
#define VHO_SWITCH_wn(i)    (VHO_Switch_Case_Table[i].wn)
243
#define VHO_SWITCH_count(i) (VHO_Switch_Case_Table[i].count)
244
#define VHO_SWITCH_freq(i)  (VHO_Switch_Case_Table[i].freq)
245
 
246
static BOOL      VHO_Switch_Signed;        /* signedness of switch index     */
247
static OPCODE    VHO_Switch_Int_Opcode;    /* opcode for Create_Int          */
248
static OPCODE    VHO_Switch_Sub_Opcode;    /* opcode for subtract            */
249
static OPCODE    VHO_Switch_EQ_Opcode;     /* opcode for == comparison       */
250
static OPCODE    VHO_Switch_LT_Opcode;     /* opcode for <  comparison       */
251
static OPCODE    VHO_Switch_GT_Opcode;     /* opcode for >  comparison       */
252
 
253
static LABEL_IDX VHO_Switch_Default_Label; /* default label in switch        */
254
static INT32     VHO_Switch_Last_Label;    /* last label in switch           */
255
static INT32   * VHO_Switch_Cluster_Table; /* table for switch clusters      */
256
static INT32     VHO_Switch_Ncases;        /* # of cases in switch           */
257
static INT32     VHO_Switch_Nclusters;     /* # of clusters in switch        */
258
static WN      * VHO_Switch_Index;         /* load of switch index           */
259
static WN      * VHO_Switch_Default_Goto;  /* goto switch default label      */
260 71 marcel
static WN      * VHO_Switch_Stmt;          /* switch statement               */
261 2 marcel
static FB_FREQ   VHO_Switch_Default_Freq;  /* goto switch default freq       */
262
 
263 135 marcel
#ifdef KEY
264
static BOOL VHO_In_MP_Region_Pragma = FALSE;
265
#endif // KEY
266
 
267 2 marcel
/* Variables related to struct lowering */
268
 
269 1470 dehao
#if defined(TARG_X8664) || defined(TARG_IA64)
270 83 marcel
INT32  VHO_Struct_Limit = 8;               /* max # of fields/statements     */
271 1950 laijx
#elif defined(TARG_NVISA)
272
INT32  VHO_Struct_Limit = 24;              /* max # of fields/statements     */
273 83 marcel
#else
274 2 marcel
INT32  VHO_Struct_Limit = 4;               /* max # of fields/statements     */
275 83 marcel
#endif
276 2 marcel
 
277
// static INT32  VHO_Struct_Alignment;      /* Alignment of struct           */
278
static BOOL   VHO_Struct_Can_Be_Lowered;    /* FALSE if cannot be lowered    */
279
static INT32  VHO_Struct_Nfields;           /* # of fields                   */
280
static TY_IDX VHO_Struct_Fld_Table [255]; /* table containing fields         */
281 71 marcel
static INT32 VHO_Struct_Offset_Table [255]; /* table containing fields offset */
282 1950 laijx
// We want to use field_ids when possible,
283
// as that gives higher-level type info about the original struct
284
// (e.g. if want to know alignment of original struct).
285
// However, fields that are arrays have a single field id,
286
// but may span multiple elements, so use element types in that case.
287
static INT32 VHO_Struct_Field_Id_Table[255]; /* table containing field ids   */
288
static BOOL VHO_Struct_Field_Is_Array_Table[255]; /* field is array? */
289 2 marcel
static INT32  VHO_Struct_Last_Field_Offset; /* offset of last field          */
290
static INT32  VHO_Struct_Last_Field_Size;   /* size of last field            */
291
 
292
#define LESS    -1
293
#define EQUAL    0
294
#define GREATER  1
295
 
296 71 marcel
#define SWITCH_key(i)  (VHO_Switch_Signed ? WN_const_val(VHO_SWITCH_wn(i)) : (UINT64) WN_const_val(VHO_SWITCH_wn(i)))
297 2 marcel
 
298
INT32
299
VHO_Switch_Compare_Value ( const void *v_item1, const void *v_item2 )
300
{
301
  INT32   compare_code;
302
  WN    * case1;
303
  WN    * case2;
304
 
305
  case1 = (( VHO_SWITCH_ITEM * ) v_item1)->wn;
306
  case2 = (( VHO_SWITCH_ITEM * ) v_item2)->wn;
307
 
308
  if ( VHO_Switch_Signed ) {
309
 
310
    if ( WN_const_val(case1) < WN_const_val(case2) )
311
      compare_code = LESS;
312
 
313
    else
314
    if ( WN_const_val(case1) > WN_const_val(case2) )
315
      compare_code = GREATER;
316
 
317
    else
318
      compare_code = EQUAL;
319
  }
320
  else {
321
 
322
    if ( (UINT64) WN_const_val(case1) < (UINT64) WN_const_val(case2) )
323
      compare_code = LESS;
324
 
325
    else
326
    if ( (UINT64) WN_const_val(case1) > (UINT64) WN_const_val(case2) )
327
      compare_code = GREATER;
328
 
329
    else
330
      compare_code = EQUAL;
331
  }
332
 
333
  return ( compare_code );
334
} /* VHO_Switch_Compare_Value */
335
 
336
 
337
/* ============================================================================
338
 *
339
 * INT32
340
 * VHO_Switch_Compare_Frequency ( const void *v_item1, const void *v_item2 )
341
 *
342
 * Routine invoked by qsort to compare two case values frequencies specified
343
 * the switch statement.
344
 *
345
 * ============================================================================
346
 */
347
 
348
INT32
349
VHO_Switch_Compare_Frequency ( const void *v_item1, const void *v_item2 )
350
{
351
  INT32   compare_code;
352
  WN    * case1;
353
  WN    * case2;
354
  FB_FREQ freq1;
355
  FB_FREQ freq2;
356
 
357
  case1  = (( VHO_SWITCH_ITEM * ) v_item1)->wn;
358
  case2  = (( VHO_SWITCH_ITEM * ) v_item2)->wn;
359
  freq1  = (( VHO_SWITCH_ITEM * ) v_item1)->freq;
360
  freq2  = (( VHO_SWITCH_ITEM * ) v_item2)->freq;
361
 
362
  if ( freq1 != freq2 ) {
363
 
364
    // Order of _decreasing_ frequencies
365
 
366
    if ( freq1 > freq2 )
367
      compare_code = LESS;
368
 
369
    else // freq1 < freq2
370
      compare_code = GREATER;
371
 
372
  } else
373
  if ( VHO_Switch_Signed ) {
374
 
375
    if ( WN_const_val(case1) < WN_const_val(case2) )
376
      compare_code = LESS;
377
 
378
    else
379
    if ( WN_const_val(case1) > WN_const_val(case2) )
380
      compare_code = GREATER;
381
 
382
    else
383
      compare_code = EQUAL;
384
  }
385
 
386
  else {
387
 
388
    if ( (UINT64) WN_const_val(case1) < (UINT64) WN_const_val(case2) )
389
      compare_code = LESS;
390
 
391
    else
392
    if ( (UINT64) WN_const_val(case1) > (UINT64) WN_const_val(case2) )
393
      compare_code = GREATER;
394
 
395
    else
396
      compare_code = EQUAL;
397
  }
398
 
399
  return ( compare_code );
400
} /* VHO_Switch_Compare_Frequency */
401
 
402 1411 laijx
#ifdef KEY
403 2 marcel
/* ============================================================================
404
 *
405
 * static WN *
406 1411 laijx
 * VHO_Switch_Generate_If_Else_Reduce_Branch ( SRCPOS srcpos )
407
 *
408
 * Generate if-else sequence for the switch statement by grouping consecutive
409
 * cases together and using a single branch for each group.
410
 *
411
 * ============================================================================
412
 */
413
static WN *
414
VHO_Switch_Generate_If_Else_Reduce_Branch (SRCPOS srcpos)
415
{
416
  WN *block, *case_goto, *wn;
417
  INT32 i, j;
418
  INT32 switch_first_label;
419
  INT32 highest_label_num, lowest_label_num;
420
  WN **labels_map;
421
 
422
  block = WN_CreateBlock();
423
  WN_Set_Linenum(block, srcpos);
424
 
425
  // Find the highest and lowest case label numbers.
426
  highest_label_num = 0;
427
  lowest_label_num = INT32_MAX;
428
  for (i = 0; i < VHO_Switch_Ncases; i++) {
429
    case_goto = VHO_SWITCH_wn(i);
430
    INT64 value = WN_label_number(case_goto);
431
    if (value > highest_label_num)
432
      highest_label_num = value;
433
    if (value < lowest_label_num)
434
      lowest_label_num = value;
435
  }
436
 
437
  // Create case labels map.
438
  INT32 size = (highest_label_num - lowest_label_num + 1) * sizeof(WN *);
439
  labels_map = (WN **) alloca(size);
440
  memset(labels_map, 0, size);
441
 
442
  // Map each case label to the first label in the case code.  A case code will
443
  // have multiple labels if it is shared by different case values.
444
  WN *first_label_in_group = (WN *) NULL;
445
  for (wn = WN_next(VHO_Switch_Stmt); ; wn = WN_next(wn)) {
446
    if (WN_operator(wn) == OPR_LABEL) {
447
      if (first_label_in_group == NULL)
448
  first_label_in_group = wn;
449
      // Map only the labels in the switch stmt.
450
      if (WN_label_number(wn) >= lowest_label_num &&
451
    WN_label_number(wn) <= highest_label_num) {
452
  labels_map[WN_label_number(wn)] = first_label_in_group;
453
      }
454
      if (WN_label_number(wn) == VHO_Switch_Last_Label)
455
  break;
456
    } else {
457
      // Real code terminates the labels group.
458
      first_label_in_group = NULL;
459
    }
460
  }
461
 
462
  // Sort the case values.
463
  qsort(VHO_Switch_Case_Table, VHO_Switch_Ncases,
464
  sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Value);
465
 
466
  for (i = 0; i < VHO_Switch_Ncases; i++) {
467
    WN *test, *sub, *tas;
468
    case_goto = VHO_SWITCH_wn(i);
469
    INT64 first_value = WN_const_val(case_goto);
470
    INT64 last_value = first_value;
471
 
472
    // Detect consecutive case values sharing common case code.
473
    for (j = i + 1; j < VHO_Switch_Ncases; j++) {
474
      WN *next_case_goto = VHO_SWITCH_wn(j);
475
      INT64 next_value = WN_const_val(next_case_goto);
476
      if (next_value != last_value + 1 ||
477
    (labels_map[WN_label_number(next_case_goto)] !=
478
     labels_map[WN_label_number(case_goto)]))
479
  break;
480
      last_value = next_value;
481
    }
482
 
483
    if (first_value == last_value) {
484
      // No consecutive case values.
485
      test = WN_CreateExp2(VHO_Switch_EQ_Opcode,
486
         WN_COPY_Tree(VHO_Switch_Index),
487
         WN_CreateIntconst(VHO_Switch_Int_Opcode,
488
               first_value));
489
      wn = WN_CreateTruebr(WN_label_number(case_goto), test);
490
      WN_Set_Linenum(wn, srcpos);
491
    } else {
492
      // Consecutive case values sharing common case code.  Translate:
493
      //
494
      //   case k:
495
      //   case k+1:
496
      //    ...
497
      //   case k+n:  goto label
498
      //
499
      // into:
500
      //
501
      //   if ((unsigned int)(index - k) <= n)
502
      //     goto label
503
      //
504
      // If index is less than k, then (unsigned int)(index - k) will be
505
      // a large unsigned int larger than n.
506
 
507
      WN *upper =
508
  WN_CreateIntconst(VHO_Switch_Int_Opcode, last_value - first_value);
509
      TYPE_ID mtype = WN_rtype(VHO_Switch_Index);
510
      sub = WN_CreateExp2(VHO_Switch_Sub_Opcode,
511
        WN_COPY_Tree(VHO_Switch_Index),
512
        WN_CreateIntconst(VHO_Switch_Int_Opcode,
513
              first_value));
514
      tas = WN_Tas(MTYPE_U4, MTYPE_To_TY(MTYPE_U4), sub);
515
      test = WN_CreateExp2(OPCODE_make_op(OPR_LE, MTYPE_U4, MTYPE_U4),
516
         tas, upper);
517
      wn = WN_CreateTruebr(WN_label_number(case_goto), test);
518
      WN_Set_Linenum(wn, srcpos);
519
      i = j - 1;    // Skip to the next case value.
520
    }
521
    WN_INSERT_BlockAfter(block, WN_last(block), wn);
522
  }
523
 
524
  WN_INSERT_BlockAfter(block, WN_last(block),
525
                       WN_COPY_Tree(VHO_Switch_Default_Goto));
526
  return block;
527
}
528
#endif
529
 
530
/* ============================================================================
531
 *
532
 * static WN *
533 2 marcel
 * VHO_Switch_Generate_If_Else ( SRCPOS srcpos )
534
 *
535
 * Generate if-else sequence for the switch statement.
536
 *
537
 * ============================================================================
538
 */
539
 
540
static WN *
541
VHO_Switch_Generate_If_Else ( SRCPOS srcpos )
542
{
543
  WN     * block;
544
  WN     * value;
545
  WN     * test;
546
  WN     * case_goto;
547
  WN     * wn;
548
  INT32    i;
549
  FB_FREQ  freq_rest;
550
 
551
  block = WN_CreateBlock();
552
  WN_Set_Linenum ( block, srcpos );
553
 
554
  if ( Cur_PU_Feedback ) {
555
 
556
    qsort ( VHO_Switch_Case_Table, VHO_Switch_Ncases,
557
            sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Frequency );
558
 
559
    freq_rest = VHO_Switch_Default_Freq;
560
    for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
561
      freq_rest += VHO_SWITCH_freq(i);
562
    }
563
 
564
  }
565
 
566
  for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
567
 
568
    case_goto = VHO_SWITCH_wn(i);
569
    value     = WN_CreateIntconst ( VHO_Switch_Int_Opcode,
570
                                    WN_const_val(case_goto) );
571
    test      = WN_CreateExp2 ( VHO_Switch_EQ_Opcode,
572
                                WN_COPY_Tree ( VHO_Switch_Index ), value );
573
    wn        = WN_CreateTruebr ( WN_label_number(case_goto), test );
574
    WN_Set_Linenum ( wn, srcpos );
575
 
576
    if ( Cur_PU_Feedback ) {
577
      freq_rest -= VHO_SWITCH_freq(i);
578
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, VHO_SWITCH_freq(i) );
579
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN, freq_rest );
580
    }
581
 
582
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
583
  }
584 71 marcel
  if ( Cur_PU_Feedback && (VHO_Switch_Ncases > 0))
585 2 marcel
    Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
586
          VHO_Switch_Default_Freq );
587
 
588
  WN_INSERT_BlockAfter ( block, WN_last(block),
589
                         WN_COPY_Tree ( VHO_Switch_Default_Goto ) );
590
 
591
  return ( block );
592
} /* VHO_Switch_Generate_If_Else */
593 71 marcel
/* ============================================================================
594
 *
595
 * static WN *
596
 * VHO_Switch_Opt_Case_Hoist ( SRCPOS srcpos )
597
 *
598
 * Generate if-else sequence for the highly biased cases.
599
 * ============================================================================
600
 */
601
static WN *
602
VHO_Switch_Opt_Case_Hoist( SRCPOS srcpos )
603
{
604
  WN     * block;
605
  WN     * value;
606
  WN     * test;
607
  WN     * case_goto;
608
  WN     * wn;
609
  INT32    i;
610
  FB_FREQ  freq_total, freq_rest, freq_top;
611
  FB_FREQ  freq_tops; // record only top 30 cases of frequencies
612
  INT32    num_hoist=0;
613 2 marcel
 
614 71 marcel
  if (!Cur_PU_Feedback ) return NULL;  // no switch optimization if no feedback
615 2 marcel
 
616 71 marcel
#ifdef KEY
617
  freq_tops = freq_total = 0.0;
618
#else
619
  freq_tops = freq_total = 0;
620
#endif
621
 
622
  block = WN_CreateBlock();
623
  WN_Set_Linenum ( block, srcpos );
624
 
625
  if ( Cur_PU_Feedback ) {
626
    qsort ( VHO_Switch_Case_Table, VHO_Switch_Ncases,
627
            sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Frequency );
628
 
629
    freq_total = VHO_Switch_Default_Freq;
630
    for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
631
      freq_total += VHO_SWITCH_freq(i);
632
 
633
      if (i < VHO_Switch_Ncases * 0.3) // top 30 % of cases
634
          freq_tops += VHO_SWITCH_freq(i);
635
    }
636
  }
637
  /* If lower than 70%, don't do switch optimization */
638
  if (freq_total.Value()<=0 || freq_tops.Value()/freq_total.Value() < 0.70)
639
      return NULL;
640
 
641
 
642
  freq_rest = freq_total;
643
 
644
  for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
645
 
646
    if ( Cur_PU_Feedback &&  VHO_SWITCH_freq(i).Value()/freq_total.Value()
647
                              < (float) VHO_Switch_Opt_Threshold/100)
648
                break;
649
#ifdef VHO_DEBUG
650
    if ( VHO_Switch_Debug )
651
      fprintf ( TFile, "SWITCH_OPT_CASE_HOIST: %d (case %d of freq %f)\n", (INT32) srcpos, i, VHO_SWITCH_freq(i).Value() );
652
#endif /* VHO_DEBUG */
653
 
654
//    printf("WARNING: SWITCH_OPT_CASE_HOIST: %d (case %d of freq %f total:%f)\n",(INT32) srcpos, i, VHO_SWITCH_freq(i).Value(), freq_total.Value());
655
 
656
    num_hoist++;
657
    case_goto = VHO_SWITCH_wn(i);
658
    value     = WN_CreateIntconst ( VHO_Switch_Int_Opcode,
659
                                    WN_const_val(case_goto) );
660
    test      = WN_CreateExp2 ( VHO_Switch_EQ_Opcode,
661
                                WN_COPY_Tree ( VHO_Switch_Index ), value );
662
    wn = WN_CreateTruebr ( WN_label_number(case_goto), test );
663
 
664
    WN_Set_Linenum ( wn, srcpos );
665
 
666
 
667
    if ( Cur_PU_Feedback ) {
668
      freq_rest -= VHO_SWITCH_freq(i);
669
      Cur_PU_Feedback->Annot_branch( wn, FB_Info_Branch( VHO_SWITCH_freq(i),
670
                        freq_rest, WN_operator( wn ) ) );
671
      Cur_PU_Feedback->FB_hoist_case(VHO_Switch_Stmt, i);
672
#ifdef KEY
673
      VHO_SWITCH_freq(i) = 0.0;
674
#else
675
      VHO_SWITCH_freq(i) = 0;
676
#endif
677
     }
678
 
679
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
680
  }
681
 
682
  /* Remove all the cases that are hoisted */
683
  for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
684
        VHO_SWITCH_wn(i) = VHO_SWITCH_wn(i + num_hoist);
685
        VHO_SWITCH_freq(i) = VHO_SWITCH_freq(i + num_hoist);
686
        VHO_SWITCH_count(i) = VHO_SWITCH_count(i+num_hoist);
687
 
688
  }
689
  VHO_Switch_Ncases = VHO_Switch_Ncases - num_hoist;
690
  VHO_SWITCH_wn(VHO_Switch_Ncases) = VHO_SWITCH_wn(VHO_Switch_Ncases - 1);
691
 
692
  return ( block );
693
 
694
} /* VHO_Switch_Opt_Case_Hoist */
695
 
696
 
697 2 marcel
/* ============================================================================
698
 *
699
 * static WN *
700
 * VHO_Switch_Generate_Compgoto ( SRCPOS srcpos )
701
 *
702
 * Generate a COMPGOTO for the switch statement.
703
 *
704
 * ============================================================================
705
 */
706
 
707
static WN *
708
VHO_Switch_Generate_Compgoto ( SRCPOS srcpos )
709
{
710
  WN      * block;
711
  WN      * test;
712
  WN      * value;
713
  WN      * wn;
714
  WN      * case_goto;
715
  INT32     i;
716
  INT32     j;
717
  INT32     n;
718
  INT64     case_value;
719
  INT64     curr_value;
720
  FB_FREQ * freq_new = NULL;
721
 
722
  block = WN_CreateBlock ();
723
  WN_Set_Linenum ( block, srcpos );
724
 
725
  case_goto  = VHO_SWITCH_wn(0);
726
  case_value = WN_const_val(case_goto);
727
  curr_value = 0;
728
  test       = WN_COPY_Tree ( VHO_Switch_Index );
729
 
730
  /* Check to see whether we can avoid generating a subtract. */
731
 
732
  if (     case_value
733
       && (UINT64)case_value > VHO_Switch_Compgoto_Limit ) {
734
 
735
    value      = WN_CreateIntconst ( VHO_Switch_Int_Opcode,
736
                                     WN_const_val(case_goto) );
737
    test       = WN_CreateExp2 ( VHO_Switch_Sub_Opcode, test, value );
738
    curr_value = case_value;
739
  }
740
 
741
  i = 0;
742
  n =   WN_const_val(VHO_SWITCH_wn(VHO_Switch_Ncases - 1))
743
      - curr_value + 1;
744
 
745
  if ( Cur_PU_Feedback )
746
    freq_new = TYPE_MEM_POOL_ALLOC_N( FB_FREQ, MEM_local_pool_ptr, n );
747
 
748
  for ( j = 0; j < n; j++ ) {
749
 
750
    if ( curr_value != case_value ) {
751
      wn = WN_COPY_Tree ( VHO_Switch_Default_Goto );
752
      if ( Cur_PU_Feedback )
753 71 marcel
//      freq_new[j] = FB_FREQ_UNKNOWN;
754
        freq_new[j] = FB_FREQ(FB_FREQ_TYPE_GUESS);  //INLINING_TUNINING
755
 
756 2 marcel
    } else {
757
 
758
      wn = WN_CreateGoto ( (ST_IDX) NULL, WN_label_number(case_goto) );
759
      if ( Cur_PU_Feedback )
760
  freq_new[j] = VHO_SWITCH_freq(i);
761
      i++;
762
      case_goto   = VHO_SWITCH_wn(i);
763
      case_value  = WN_const_val(case_goto);
764
    }
765
 
766
    WN_Set_Linenum ( wn, srcpos );
767
 
768
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
769
    curr_value++;
770
  }
771
 
772
  wn = WN_CreateCompgoto ( n, test, block, VHO_Switch_Default_Goto,
773
                           VHO_Switch_Last_Label );
774
 
775
  if ( Cur_PU_Feedback ) {
776
 
777
    FB_Info_Switch info_switch( n );
778
    info_switch[ FB_EDGE_SWITCH_INDEX( FB_EDGE_SWITCH_DEFAULT ) ]
779 71 marcel
//      = FB_FREQ_UNKNOWN; // not VHO_Switch_Default_Freq
780
        = FB_FREQ(VHO_Switch_Default_Freq.Value(), FALSE);//INLINING_TUNINING
781 2 marcel
    for ( j = 0; j < n; j++ )
782
      info_switch[ FB_EDGE_SWITCH_INDEX( FB_EDGE_SWITCH( j ) ) ] = freq_new[j];
783
    Cur_PU_Feedback->Annot_switch( wn, info_switch );
784
 
785
    MEM_POOL_FREE( MEM_local_pool_ptr, freq_new );
786
  }
787
 
788
  return wn;
789
} /* VHO_Switch_Generate_Compgoto */
790
 
791
 
792
/* ============================================================================
793
 *
794
 * static void
795
 * VHO_Switch_Generate_Binary_Search ( INT32 left, INT32 right, WN * block )
796
 *
797
 * Implement the switch statement as a binary search.
798
 * left and right give the indices in VHO_Switch_Case_Table which
799
 * contain the values to be compared with.
800
 * block contains the WHIRL block node to which statements are to be added.
801
 *
802
 * ============================================================================
803
 */
804
 
805
static void
806
VHO_Switch_Generate_Binary_Search ( INT32 left, INT32 right, WN * block )
807
{
808
  INT32    mid;
809
  INT64    value;
810
  WN     * test;
811
  WN     * wn;
812
  SRCPOS   srcpos;
813
 
814
  LABEL_IDX lt_label;
815
  LABEL_IDX gt_label;
816
 
817
  srcpos = WN_Get_Linenum(block);
818
 
819
  mid   = ( left + right + 1 ) >> 1;
820
  value = WN_const_val(VHO_SWITCH_wn(mid));
821
 
822
 
823
  if (mid > left)
824
    LABEL_Init (New_LABEL (CURRENT_SYMTAB, lt_label), 0, LKIND_DEFAULT);
825
  else
826
    lt_label = VHO_Switch_Default_Label;
827
 
828
  if (mid < right)
829
    LABEL_Init (New_LABEL (CURRENT_SYMTAB, gt_label), 0, LKIND_DEFAULT);
830
  else
831
    gt_label = VHO_Switch_Default_Label;
832
 
833
  if ( lt_label == gt_label ) {
834
 
835
    test = WN_CreateExp2 ( VHO_Switch_EQ_Opcode,
836
                           WN_COPY_Tree ( VHO_Switch_Index ),
837
                           WN_CreateIntconst ( VHO_Switch_Int_Opcode,
838
                                               value ) );
839
    wn = WN_CreateFalsebr ( lt_label, test );
840
    WN_Set_Linenum ( wn, srcpos );
841
    if ( Cur_PU_Feedback ) {
842
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
843
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
844
            VHO_SWITCH_freq( mid ) );
845
    }
846
 
847
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
848
  }
849
 
850
  else {
851
 
852
    test = WN_CreateExp2 ( VHO_Switch_LT_Opcode,
853
                           WN_COPY_Tree ( VHO_Switch_Index ),
854
                           WN_CreateIntconst ( VHO_Switch_Int_Opcode,
855
                                               value ) );
856
    wn = WN_CreateTruebr ( lt_label, test );
857
    WN_Set_Linenum ( wn, srcpos );
858
    if ( Cur_PU_Feedback ) {
859
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
860
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
861
            FB_FREQ_UNKNOWN );
862
    }
863
 
864
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
865
 
866
    test = WN_CreateExp2 ( VHO_Switch_GT_Opcode,
867
                           WN_COPY_Tree ( VHO_Switch_Index ),
868
                           WN_CreateIntconst ( VHO_Switch_Int_Opcode,
869
                                               value ) );
870
    wn = WN_CreateTruebr ( gt_label, test );
871
    WN_Set_Linenum ( wn, srcpos );
872
    if ( Cur_PU_Feedback ) {
873
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
874
      Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
875
            VHO_SWITCH_freq( mid ) );
876
    }
877
 
878
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
879
  }
880
 
881
  wn = WN_CreateGoto ( (ST_IDX) NULL, WN_label_number(VHO_SWITCH_wn(mid)) );
882
  WN_Set_Linenum ( wn, srcpos );
883
  if ( Cur_PU_Feedback )
884
    Cur_PU_Feedback->Annot( wn, FB_EDGE_OUTGOING, VHO_SWITCH_freq( mid ) );
885
 
886
  WN_INSERT_BlockAfter ( block, WN_last(block), wn );
887
 
888
  if ( mid > left ) {
889
 
890
    wn = WN_CreateLabel ( (ST_IDX) 0, lt_label, 0, NULL );
891
    WN_Set_Linenum ( wn, srcpos );
892
 
893
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
894
    VHO_Switch_Generate_Binary_Search ( left, mid - 1, block );
895
  }
896
 
897
  if ( mid < right ) {
898
 
899
    wn = WN_CreateLabel ( (ST_IDX) 0, gt_label, 0, NULL );
900
    WN_Set_Linenum ( wn, srcpos );
901
 
902
    WN_INSERT_BlockAfter ( block, WN_last(block), wn );
903
    VHO_Switch_Generate_Binary_Search ( mid + 1, right, block );
904
  }
905
} /* VHO_Switch_Generate_Binary_Search */
906
 
907
/* ============================================================================
908
 *
909
 * static void
910
 * VHO_Switch_Find_Clusters ( void )
911
 *
912
 * Group the switch values into clusters.
913
 * For each cluster a COMPGOTO cna be generated.
914
 *
915
 * ============================================================================
916
 */
917
 
918
static void
919
VHO_Switch_Find_Clusters ( void )
920
{
921
  INT32   i;
922
  INT32   j;
923
  INT32   k;
924
  INT32   n;
925
 
926
  qsort ( VHO_Switch_Case_Table, VHO_Switch_Ncases,
927
          sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Value );
928
 
929
#ifdef VHO_DEBUG
930
  if ( VHO_Switch_Debug ) {
931
 
932
    fprintf ( TFile, "SWITCH TABLE after sorting\n" );
933
 
934
    for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
935
 
936
      case_goto = VHO_SWITCH_wn(i);
937
      fprintf ( TFile, VHO_Switch_Format, i,
938
                WN_const_val(case_goto), WN_label_number(case_goto) );
939
    }
940
  }
941
#endif /* VHO_DEBUG */
942
 
943
  j = 0;
944
  VHO_Switch_Cluster_Table [0] = 0;
945
 
946
  for ( i = 1; i < VHO_Switch_Ncases; i++ ) {
947
 
948
    if (    ( i - VHO_Switch_Cluster_Table [j] ) * VHO_Switch_Density
949
         >= SWITCH_key(i) - SWITCH_key(VHO_Switch_Cluster_Table[j]) ) {
950
 
951
      if (j > 0) {
952
 
953
        if (    ( i - VHO_Switch_Cluster_Table [j-1] ) * VHO_Switch_Density
954
             >= SWITCH_key(i) - SWITCH_key(VHO_Switch_Cluster_Table[j-1]) )
955
          j--;
956
      }
957
    }
958
 
959
    else
960
      VHO_Switch_Cluster_Table [++j] = i;
961
  }
962
 
963
  VHO_Switch_Cluster_Table [++j] = VHO_Switch_Ncases;
964
 
965
  VHO_Switch_Nclusters = 0;
966
 
967
  for ( i = 0; i < j; i++ ) {
968
 
969
    if (   VHO_Switch_Cluster_Table [i+1] - VHO_Switch_Cluster_Table [i]
970
         > VHO_Switch_If_Else_Limit )
971
      VHO_Switch_Nclusters++;
972
 
973
    else
974
      VHO_Switch_Nclusters +=
975
        VHO_Switch_Cluster_Table [i+1] - VHO_Switch_Cluster_Table [i];
976
  }
977
 
978
  if ( VHO_Switch_Nclusters > j ) {
979
 
980
    i = VHO_Switch_Nclusters;
981
 
982
    while ( j > 0 ) {
983
 
984
      n = VHO_Switch_Cluster_Table [j] - VHO_Switch_Cluster_Table [j-1];
985
 
986
      if ( n > VHO_Switch_If_Else_Limit )
987
        VHO_Switch_Cluster_Table [i--] = VHO_Switch_Cluster_Table [j];
988
 
989
      else {
990
 
991
        for ( k = 0; k < n; k++ )
992
          VHO_Switch_Cluster_Table [i--] = VHO_Switch_Cluster_Table [j] - k;
993
 
994
        if ( i < j )
995
          break;
996
      }
997
 
998
      --j;
999
    }
1000
  }
1001
 
1002
#ifdef VHO_DEBUG
1003
  if ( VHO_Switch_Debug ) {
1004
 
1005
    fprintf (TFile, "  VHO_Switch_Nclusters = %d\n", VHO_Switch_Nclusters);
1006
 
1007
    for ( i = 0; i <= VHO_Switch_Nclusters; i++ )
1008
      fprintf (TFile, "  VHO_Switch_Cluster_Table [%2d] = %2d\n",
1009
               i, VHO_Switch_Cluster_Table [i]);
1010
  }
1011
#endif /* VHO_DEBUG */
1012
} /* VHO_Switch_Find_Clusters */
1013
 
1014
/* ============================================================================
1015
 *
1016
 * static WN *
1017
 * VHO_Lower_Switch ( WN * wn )
1018
 *
1019
 * Lower a switch statement into a combination of
1020
 *
1021
 *   if-else
1022
 *   COMPGOTO
1023
 *   binary search.
1024
 *
1025
 * ============================================================================
1026
 */
1027
 
1028
static WN *
1029
VHO_Lower_Switch ( WN * wn )
1030
{
1031
  WN       * block;
1032
  WN       * case_goto;
1033
  TYPE_ID    mtype;
1034
  INT32      i;
1035
  INT32      j;
1036
  SRCPOS     srcpos;
1037
  INT32      count;
1038 71 marcel
  WN       * conv_wn = NULL;
1039 2 marcel
 
1040
  LABEL_IDX  last_label;
1041
 
1042
  srcpos = WN_Get_Linenum(wn);
1043
  block  = WN_kid1(wn);
1044
 
1045 71 marcel
  VHO_Switch_Stmt         = wn;
1046 2 marcel
  VHO_Switch_Index        = WN_kid0(wn);
1047
  VHO_Switch_Default_Goto = ( WN_kid_count(wn) == 3 ) ? WN_kid2(wn) : NULL;
1048
  VHO_Switch_Last_Label   = WN_last_label(wn);
1049
 
1050
  mtype = WN_rtype (VHO_Switch_Index);
1051
 
1052
  VHO_Switch_Int_Opcode = OPCODE_make_op ( OPR_INTCONST,
1053
                                           Promoted_Mtype [mtype],
1054
                                           MTYPE_V );
1055
  VHO_Switch_Sub_Opcode = OPCODE_make_op ( OPR_SUB,
1056
                                           Promoted_Mtype [mtype],
1057
                                           MTYPE_V );
1058
  VHO_Switch_EQ_Opcode  = OPCODE_make_op ( OPR_EQ,
1059
                                           MTYPE_I4,
1060
                                           Promoted_Mtype [mtype] );
1061
  VHO_Switch_LT_Opcode  = OPCODE_make_op ( OPR_LT,
1062
                                           MTYPE_I4,
1063
                                           Promoted_Mtype [mtype] );
1064
  VHO_Switch_GT_Opcode  = OPCODE_make_op ( OPR_GT,
1065
                                           MTYPE_I4,
1066
                                           Promoted_Mtype [mtype] );
1067
 
1068
#ifdef VHO_DEBUG
1069
  if ( VHO_Switch_Debug )
1070
    fprintf ( TFile, "SWITCH TABLE before sorting\n" );
1071
#endif /* VHO_DEBUG */
1072
 
1073
  switch ( mtype ) {
1074
 
1075
  case MTYPE_I1:
1076
  case MTYPE_I2:
1077
  case MTYPE_I4:
1078
  case MTYPE_I8:
1079
 
1080
#ifdef VHO_DEBUG
1081
    VHO_Switch_Format = "  [%2d] value = %lld, label = %d\n";
1082
#endif /* VHO_DEBUG */
1083
 
1084
    VHO_Switch_Signed = TRUE;
1085
    break;
1086
 
1087
  case MTYPE_U1:
1088
  case MTYPE_U2:
1089
  case MTYPE_U4:
1090
  case MTYPE_U8:
1091
 
1092
#ifdef VHO_DEBUG
1093
    VHO_Switch_Format = "  [%2d] value = %llu, label = %d\n";
1094
#endif /* VHO_DEBUG */
1095
 
1096
    VHO_Switch_Signed = FALSE;
1097
    break;
1098
  }
1099
 
1100
  for ( VHO_Switch_Ncases = 0, case_goto = WN_first(block);
1101
        case_goto;
1102
        VHO_Switch_Ncases++, case_goto = WN_next(case_goto) ) {
1103
 
1104
#ifdef VHO_DEBUG
1105
    if ( VHO_Switch_Debug )
1106
      fprintf ( TFile, VHO_Switch_Format, VHO_Switch_Ncases,
1107
    WN_const_val(case_goto), WN_label_number(case_goto) );
1108
#endif /* VHO_DEBUG */
1109
 
1110
  }
1111
 
1112
  if ( Cur_PU_Feedback ) {
1113
    VHO_Switch_Default_Freq
1114
      = ( VHO_Switch_Default_Goto
1115
    ? Cur_PU_Feedback->Query( wn, FB_EDGE_SWITCH_DEFAULT )
1116
    : FB_FREQ_ZERO );
1117
  }
1118
 
1119
  VHO_Switch_Case_Table =
1120
    TYPE_MEM_POOL_ALLOC_N(VHO_SWITCH_ITEM,
1121
                          MEM_local_pool_ptr, (VHO_Switch_Ncases+1));
1122
  VHO_Switch_Cluster_Table =
1123
    TYPE_MEM_POOL_ALLOC_N(INT32, MEM_local_pool_ptr, (VHO_Switch_Ncases+1));
1124
 
1125
  last_label = INT32_MIN;
1126
 
1127
  for ( i = 0, case_goto = WN_first(block);
1128
        i < VHO_Switch_Ncases;
1129
        i++, case_goto = WN_next(case_goto) ) {
1130
 
1131
    VHO_SWITCH_wn(i) = case_goto;
1132
    if ( Cur_PU_Feedback )
1133
      VHO_SWITCH_freq(i) = Cur_PU_Feedback->Query( wn, FB_EDGE_SWITCH( i ) );
1134
 
1135
    if ( WN_label_number(case_goto) == last_label )
1136
      count++;
1137
 
1138
    else {
1139
 
1140
      for ( j = i - 1; j >= 0; --j ) {
1141
 
1142
        if ( last_label == WN_label_number(VHO_SWITCH_wn(j)) )
1143
          VHO_SWITCH_count(j) = count;
1144
 
1145
        else
1146
          break;
1147
      }
1148
 
1149
      count = 1;
1150
      last_label = WN_label_number(case_goto);
1151
    }
1152
  }
1153
 
1154
  for ( j = i - 1; j >= 0; --j ) {
1155
 
1156
    if ( last_label == WN_label_number(VHO_SWITCH_wn(j)) )
1157
      VHO_SWITCH_count(j) = count;
1158
 
1159
    else
1160
      break;
1161
  }
1162
 
1163
  VHO_SWITCH_wn(VHO_Switch_Ncases) = VHO_SWITCH_wn(VHO_Switch_Ncases - 1);
1164
 
1165
  for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
1166
 
1167
    case_goto = VHO_SWITCH_wn(i);
1168
  }
1169
 
1170
  if ( VHO_Switch_Ncases <= VHO_Switch_If_Else_Limit ) {
1171
 
1172
#ifdef VHO_DEBUG
1173
    if ( VHO_Switch_Debug )
1174
      fprintf ( TFile, "SWITCH_If_Else %d\n", (INT32) srcpos );
1175
#endif /* VHO_DEBUG */
1176
 
1177 1411 laijx
#ifdef KEY
1178 1950 laijx
    if ( !Cur_PU_Feedback &&
1179
         VHO_Switch_Reduce_Branch) {
1180 1411 laijx
      wn = VHO_Switch_Generate_If_Else_Reduce_Branch(srcpos);
1181
    } else
1182
#endif
1183 2 marcel
    wn = VHO_Switch_Generate_If_Else ( srcpos );
1184
  }
1185
 
1186
  else {
1187 71 marcel
   if (VHO_Switch_Opt)
1188
       conv_wn = VHO_Switch_Opt_Case_Hoist ( srcpos );
1189 2 marcel
 
1190 71 marcel
#ifdef VHO_DEBUG
1191
   if ( VHO_Switch_Debug )
1192
       fprintf ( TFile, "SWITCH_OPT %d\n", (INT32) srcpos );
1193
#endif /* VHO_DEBUG */
1194
 
1195 2 marcel
    VHO_Switch_Find_Clusters ();
1196
 
1197
    if ( VHO_Switch_Nclusters == 1 ) {
1198
 
1199
#ifdef VHO_DEBUG
1200
      if ( VHO_Switch_Debug )
1201
        fprintf ( TFile, "SWITCH_Compgoto %d\n", (INT32) srcpos );
1202
#endif /* VHO_DEBUG */
1203
 
1204
      wn = VHO_Switch_Generate_Compgoto ( srcpos );
1205
    }
1206
 
1207
    else {
1208
 
1209
#ifdef VHO_DEBUG
1210
      if ( VHO_Switch_Debug )
1211
        fprintf ( TFile, "SWITCH_binary %d\n", (INT32) srcpos );
1212
#endif /* VHO_DEBUG */
1213
 
1214
      wn = WN_CreateBlock ();
1215
      WN_Set_Linenum ( wn, srcpos );
1216
 
1217
      if (VHO_Switch_Default_Goto)
1218
        VHO_Switch_Default_Label = WN_label_number(VHO_Switch_Default_Goto);
1219
      else
1220
      LABEL_Init (New_LABEL (CURRENT_SYMTAB, VHO_Switch_Default_Label),
1221
    0, LKIND_DEFAULT);
1222
 
1223
      VHO_Switch_Generate_Binary_Search ( 0, VHO_Switch_Ncases-1, wn );
1224
    }
1225
  }
1226
 
1227
  MEM_POOL_FREE ( MEM_local_pool_ptr, VHO_Switch_Case_Table );
1228
  MEM_POOL_FREE ( MEM_local_pool_ptr, VHO_Switch_Cluster_Table );
1229 71 marcel
  if (conv_wn == NULL)
1230
        return wn;
1231
  else {
1232
     WN_INSERT_BlockAfter (conv_wn, WN_last(conv_wn),  wn);
1233
     return conv_wn;
1234
  }
1235 2 marcel
 
1236
  return wn;
1237
} /* VHO_Lower_Switch */
1238
 
1239
/* ============================================================================
1240
 *
1241
 * static WN *
1242
 * VHO_Lower_Compgoto ( WN * wn )
1243
 *
1244
 * ============================================================================
1245
 */
1246
 
1247
static WN *
1248
VHO_Lower_Compgoto ( WN * wn )
1249
{
1250
  return wn;
1251
} /* VHO_Lower_Compgoto */
1252
 
1253
 
1254
/* ============================================================================
1255
 *
1256 1950 laijx
 * static UINT
1257 2 marcel
 * VHO_Get_Field_List ( WN_OFFSET offset, TY_IDX sty_idx )
1258
 *
1259
 * Flatten a struct/union 'sty' starting as 'offset' into non overlapping
1260
 * fields and place them in the array VHO_Struct_Fld_Table.
1261
 * Update VHO_Struct_Nfields, VHO_Struct_Last_Field_Offset
1262
 * VHO_Struct_Last_Field_Size.
1263
 *
1264
 * If the structure contains misaligned data, holes or fields which
1265
 * are out of order, then lowering is not done.
1266
 * This is done by setting VHO_Struct_Can_Be_Lowered to FALSE.
1267
 *
1268
 * ============================================================================
1269
 */
1270
 
1271 1950 laijx
static UINT
1272
VHO_Get_Field_List ( WN_OFFSET offset, TY_IDX sty_idx, UINT field_id )
1273 2 marcel
{
1274
  TY_IDX      fty_idx;
1275
  WN_OFFSET   field_offset;
1276
 
1277
  if ( TY_fld(Ty_Table [sty_idx]).Is_Null () ) {
1278
    VHO_Struct_Can_Be_Lowered = FALSE;
1279 1950 laijx
    return field_id;
1280 2 marcel
  }
1281
 
1282
  FLD_ITER fld_iter = Make_fld_iter (TY_fld (Ty_Table[sty_idx]));
1283
 
1284
  while (VHO_Struct_Can_Be_Lowered) {
1285
    FLD_HANDLE fld (fld_iter);
1286
    if ( FLD_is_bit_field(fld) ) {
1287
      VHO_Struct_Can_Be_Lowered = FALSE;
1288
      break;
1289
    }
1290
    fty_idx = FLD_type(fld);
1291
    switch ( TY_kind(Ty_Table [fty_idx]) ) {
1292
 
1293
      case KIND_SCALAR:
1294
      case KIND_POINTER:
1295
        field_offset = offset + FLD_ofst(fld);
1296 1950 laijx
        // always increase the field_id for SCALAR and POINTER
1297
        ++field_id;
1298 2 marcel
        if ( VHO_Struct_Nfields ) {
1299 1950 laijx
          if ( field_offset >= VHO_Struct_Last_Field_Offset
1300
                                 + VHO_Struct_Last_Field_Size ) {
1301 2 marcel
            /* new field */
1302
            VHO_Struct_Last_Field_Offset = field_offset;
1303
            VHO_Struct_Last_Field_Size   = TY_size (Ty_Table [fty_idx]);
1304 1950 laijx
            VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = FALSE;
1305
            VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
1306 71 marcel
            VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset;
1307 2 marcel
            VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = fty_idx;
1308
          }
1309
          else
1310
          if ( field_offset == VHO_Struct_Last_Field_Offset ) {
1311
            /* overlapping field with same start offset */
1312
            if ( TY_size (Ty_Table [fty_idx]) > VHO_Struct_Last_Field_Size ) {
1313
              /* overlapping field with larger size */
1314
              VHO_Struct_Last_Field_Offset = field_offset;
1315
              VHO_Struct_Last_Field_Size   = TY_size (Ty_Table [fty_idx]);
1316 1950 laijx
              VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = FALSE;
1317
              VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
1318 2 marcel
              VHO_Struct_Fld_Table [VHO_Struct_Nfields-1] = fty_idx;
1319 71 marcel
              VHO_Struct_Offset_Table [VHO_Struct_Nfields-1] = field_offset;
1320 2 marcel
            }
1321
          }
1322
          else
1323 1950 laijx
          if ( field_offset + TY_size (Ty_Table [fty_idx])
1324
                   > VHO_Struct_Last_Field_Offset + VHO_Struct_Last_Field_Size ) {
1325 2 marcel
            VHO_Struct_Can_Be_Lowered = FALSE;
1326
          }
1327
        }
1328
 
1329
        else {
1330
          /* new field */
1331
          VHO_Struct_Last_Field_Offset = field_offset;
1332
          VHO_Struct_Last_Field_Size   = TY_size (Ty_Table [fty_idx]);
1333 1950 laijx
          VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = FALSE;
1334
          VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
1335 71 marcel
          VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset;
1336 2 marcel
          VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = fty_idx;
1337
        }
1338
        break;
1339
 
1340
      case KIND_STRUCT:
1341
 
1342
        if ( TY_is_packed(Ty_Table[fty_idx] ))
1343
          VHO_Struct_Can_Be_Lowered = FALSE;
1344 1950 laijx
        else {
1345
          // Structs are their own field id,
1346
          // then each field in them gets new id.
1347
          // So increment field_id,
1348
          // but don't want whole struct in table, just each subfield.
1349
          ++field_id;
1350
 
1351
          // get new field id from sub-struct
1352
          // so next field will have right value.
1353
          field_id = VHO_Get_Field_List (offset + FLD_ofst (fld), fty_idx, field_id);
1354
        }
1355 2 marcel
        break;
1356
 
1357 71 marcel
      case KIND_ARRAY:
1358
        INT32   array_elem_num;
1359
  TY_IDX  ety_idx;
1360
 
1361
        ety_idx = Ty_Table [fty_idx].Etype();
1362 135 marcel
#ifdef KEY // bug 5273: array element size can be zero
1363 1950 laijx
       if (TY_size(Ty_Table[ety_idx]) == 0)
1364
         array_elem_num = 0;
1365
       else {
1366 135 marcel
#endif
1367 1950 laijx
         Is_True (TY_size(Ty_Table [fty_idx])%TY_size(Ty_Table [ety_idx]) == 0,
1368 71 marcel
                       ("unexpected array type"));
1369 1950 laijx
         array_elem_num = TY_size(Ty_Table [fty_idx])/TY_size(Ty_Table [ety_idx]);
1370 135 marcel
#ifdef KEY // bug 5273
1371 1950 laijx
       }
1372 135 marcel
#endif
1373 71 marcel
        // Is_True (VHO_Struct_Nfields + array_elem_num < 255,
1374
        //            ("number of flattened fields exceeds limit");
1375
        if (VHO_Struct_Nfields + array_elem_num >= 255) {
1376 1950 laijx
          VHO_Struct_Can_Be_Lowered = FALSE;
1377
          break;
1378 71 marcel
        }
1379 1950 laijx
  ++field_id; // keep same field_id for all array elements
1380 71 marcel
        field_offset = offset + FLD_ofst(fld);
1381
 
1382
        if(VHO_Struct_Nfields) {
1383 1950 laijx
          if ( field_offset >=  VHO_Struct_Last_Field_Offset
1384
                                  + VHO_Struct_Last_Field_Size ) {
1385 71 marcel
            for(int i=0; i<array_elem_num; i++) {
1386 1950 laijx
              if (TY_kind(ety_idx) == KIND_STRUCT) {
1387
                INT last_nfield = VHO_Struct_Nfields;
1388
                // array of structs; open up each field of struct
1389
                VHO_Get_Field_List (field_offset + i*TY_size(ety_idx),
1390
                                    ety_idx, field_id);
1391
                for (INT j=last_nfield; j < VHO_Struct_Nfields; ++j) {
1392
                  VHO_Struct_Field_Is_Array_Table [j] = TRUE;
1393
                  VHO_Struct_Field_Id_Table [j] = field_id;
1394
                }
1395
              }
1396
              else {
1397
                VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = TRUE;
1398
                VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
1399
                VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset + i*TY_size(Ty_Table [ety_idx]);
1400
                VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = ety_idx;
1401
              }
1402 71 marcel
            }
1403
            VHO_Struct_Last_Field_Offset = field_offset;
1404
            VHO_Struct_Last_Field_Size   = TY_size(Ty_Table [fty_idx]);
1405
          } else if ( field_offset == VHO_Struct_Last_Field_Offset ) {
1406
            if ( TY_size (Ty_Table [fty_idx]) > VHO_Struct_Last_Field_Size ) {
1407
              VHO_Struct_Nfields--;
1408
              for(int i=0; i<array_elem_num; i++) {
1409 1950 laijx
                if (TY_kind(ety_idx) == KIND_STRUCT) {
1410
                  INT last_nfield = VHO_Struct_Nfields;
1411
                  // array of structs; open up each field of struct
1412
                  VHO_Get_Field_List (field_offset + i*TY_size(ety_idx),
1413
                                      ety_idx, field_id);
1414
                  for (INT j=last_nfield; j < VHO_Struct_Nfields; ++j) {
1415
                    VHO_Struct_Field_Is_Array_Table [j] = TRUE;
1416
                    VHO_Struct_Field_Id_Table [j] = field_id;
1417
                  }
1418
                }
1419
                else {
1420
                  VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = TRUE;
1421
                  VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
1422
                  VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset + i*TY_size(Ty_Table [ety_idx]);
1423
                  VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = ety_idx;
1424
                }
1425 71 marcel
              }
1426
              VHO_Struct_Last_Field_Offset = field_offset;
1427
              VHO_Struct_Last_Field_Size   = TY_size(Ty_Table [fty_idx]);
1428
            }
1429
          } else if ( field_offset + TY_size (Ty_Table [fty_idx])
1430 1950 laijx
                        > VHO_Struct_Last_Field_Offset + VHO_Struct_Last_Field_Size ) {
1431 71 marcel
            VHO_Struct_Can_Be_Lowered = FALSE;
1432
          }
1433
        }
1434
        else {
1435
          for(int i=0; i<array_elem_num; i++) {
1436 1950 laijx
            if (TY_kind(ety_idx) == KIND_STRUCT) {
1437
              INT last_nfield = VHO_Struct_Nfields;
1438
              // array of structs; open up each field of struct
1439
              VHO_Get_Field_List (field_offset + i*TY_size(ety_idx),
1440
                                  ety_idx, field_id);
1441
              for (INT j=last_nfield; j < VHO_Struct_Nfields; ++j) {
1442
                VHO_Struct_Field_Is_Array_Table [j] = TRUE;
1443
                VHO_Struct_Field_Id_Table [j] = field_id;
1444
              }
1445
            }
1446
            else {
1447
                VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = TRUE;
1448
                VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
1449
                VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset + i*TY_size(Ty_Table [ety_idx]);
1450
                VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = ety_idx;
1451
            }
1452 71 marcel
          }
1453
          VHO_Struct_Last_Field_Offset = field_offset;
1454
          VHO_Struct_Last_Field_Size   = TY_size(Ty_Table [fty_idx]);
1455
        }
1456
        break;
1457
 
1458 2 marcel
      default:
1459
 
1460
        VHO_Struct_Can_Be_Lowered = FALSE;
1461
        break;
1462
    }
1463
 
1464
    if (FLD_last_field (fld))
1465
      break;
1466
    else
1467
      ++fld_iter;
1468
  }
1469 1950 laijx
  return field_id;
1470 2 marcel
 
1471
} /* VHO_Get_Field_List */
1472
 
1473 749 hucheng
#ifdef KEY
1474
// If there is a single field that spans across the entire
1475
// struct (i.e. any other field has size zero), return the field-id,
1476
// else return 0.
1477
static INT
1478
single_field_in_struct (TY_IDX struct_type)
1479
{
1480
  Is_True (TY_kind(struct_type) == KIND_STRUCT,
1481
           ("single_field_in_struct: expected struct type"));
1482
 
1483
  Is_True (TY_size(struct_type) == 4 || TY_size(struct_type) == 8,
1484
           ("single_field_in_struct: sizes 4/8 only supported"));
1485
  FLD_ITER fld_iter = Make_fld_iter (TY_fld (struct_type));
1486
  INT fld_count = 0;
1487
 
1488
  do {
1489
    FLD_HANDLE fld(fld_iter);
1490
    fld_count++;
1491 861 hucheng
    if (! FLD_is_bit_field(fld) &&
1492
        TY_size (FLD_type (fld)) == TY_size (struct_type))
1493 749 hucheng
      return fld_count;
1494
    // Else if there is a field with non-zero size, then there must be
1495
    // multiple non-zero-size fields.
1496
    else if (TY_size (FLD_type (fld)))
1497
      return 0;
1498
  } while (!FLD_last_field(fld_iter++));
1499
 
1500
  return 0;
1501
}
1502
#endif
1503
 
1504 1950 laijx
static TY_IDX
1505
get_field_type (TY_IDX struct_type, UINT field_id)
1506
{
1507
  Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
1508
  UINT cur_field_id = 0;
1509
  FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
1510
  Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
1511
                          field_id, struct_type));
1512
  return FLD_type (fld);
1513
}
1514
 
1515 2 marcel
/* ============================================================================
1516
 *
1517
 * WN *VHO_Lower_Mstore ( WN * wn )
1518
 *
1519
 * If the structure being copied is sufficiently small, then flatten out the
1520
 * structure into a set of non overlapping fields and load/store the
1521
 * individual fields, thereby replacing MSTORE/MLOAD by a sequence of
1522
 * one or more (controlled by VHO_Struct_Limit) pairs of STID/ISTORE
1523
 * over LDID/ILOAD.
1524
 *
1525
 * The following structures are not currently handled.
1526
 *
1527
 *   structures containing misaligned fields
1528
 *   structures containing bit fields
1529
 *   structures containing arrays
1530
 *
1531
 * ============================================================================
1532
 */
1533
 
1534
WN *
1535
VHO_Lower_Mstore ( WN * wn )
1536
{
1537
  WN_OFFSET   dst_offset;
1538
  WN        * dst_address;
1539
  TY_IDX      ptr_dst_ty_idx;
1540
  TY_IDX      dst_ty_idx;
1541 71 marcel
  ST        * dst_st = NULL;
1542 2 marcel
  WN        * src_value;
1543
  WN_OFFSET   src_offset;
1544
  WN        * src_address;
1545
  TY_IDX      ptr_src_ty_idx;
1546
  TY_IDX      src_ty_idx;
1547
  ST        * src_st;
1548
  WN        * size;
1549
  INT64       bytes;
1550
  WN        * block;
1551 71 marcel
  // WN_OFFSET   field_offset;
1552 2 marcel
  INT32       i;
1553
  SRCPOS      srcpos;
1554
  WN        * temp;
1555
  PREG_NUM    preg;
1556
  ST        * preg_st;
1557
  TY_IDX      preg_ty_idx;
1558
  OPCODE      opc;
1559
 
1560
  src_value      = WN_kid0(wn);
1561
  dst_address    = WN_kid1(wn);
1562
  size           = WN_kid(wn,2);
1563
  dst_offset     = WN_store_offset(wn);
1564
  ptr_dst_ty_idx = WN_ty(wn);
1565
  srcpos         = WN_Get_Linenum(wn);
1566
 
1567 1950 laijx
  if ( VHO_Struct_Opt
1568 2 marcel
       && WN_operator(size) == OPR_INTCONST
1569
       && WN_opcode(src_value) == OPC_MLOAD ) {
1570 71 marcel
       /* need to handle WN_opcode(src_value) == OPC_MMLDID,
1571
          see VHO_Lower_Mstid function                        */
1572 2 marcel
 
1573
    bytes          = WN_const_val(size);
1574
    src_address    = WN_kid0(src_value);
1575
    ptr_src_ty_idx = WN_ty(src_value);
1576
    src_ty_idx     = TY_pointed(Ty_Table[ptr_src_ty_idx]);
1577 71 marcel
    if (WN_field_id(src_value) != 0) {
1578
       src_ty_idx = get_field_type(src_ty_idx, WN_field_id(src_value));
1579
    }
1580
 
1581 2 marcel
    dst_ty_idx     = TY_pointed(Ty_Table[ptr_dst_ty_idx]);
1582 71 marcel
    if (WN_field_id(wn) != 0) {
1583
       dst_ty_idx = get_field_type(dst_ty_idx, WN_field_id(wn));
1584
    }
1585 2 marcel
 
1586 1950 laijx
    // Used to check for matching struct alignment,
1587
    // but we don't need alignment to match to copy fields
1588
    // (may have been related to unused VHO_Struct_Alignment variable).
1589
    // if (    TY_align(src_ty_idx) == TY_align(dst_ty_idx)
1590
    if (TY_kind(src_ty_idx) == KIND_STRUCT
1591 2 marcel
         && TY_is_packed(Ty_Table[src_ty_idx]) == FALSE
1592
         && TY_is_packed(Ty_Table[dst_ty_idx]) == FALSE
1593
         && bytes / TY_align(src_ty_idx) <= VHO_Struct_Limit ) {
1594
 
1595
      VHO_Struct_Nfields = 0;
1596
      VHO_Struct_Can_Be_Lowered = TRUE;
1597
//    VHO_Struct_Alignment = TY_align(dst_ty_idx);
1598
 
1599
      /* Flatten out the structure into non overlapping fields */
1600 1950 laijx
      VHO_Get_Field_List ( 0, src_ty_idx, WN_field_id(src_value) );
1601 2 marcel
 
1602
#ifdef VHO_DEBUG
1603
      if ( VHO_Struct_Debug )
1604
        fprintf ( TFile, "VHO_Lower_Mstore : %s %d\n",
1605
                  VHO_Struct_Can_Be_Lowered ? "TRUE" : "FALSE",
1606
                  (INT32) srcpos );
1607
#endif /* VHO_DEBUG */
1608
 
1609
      if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields ) {
1610
 
1611
        block = WN_CreateBlock ();
1612
        WN_Set_Linenum ( block, srcpos );
1613
 
1614
        src_offset = WN_offset(src_value);
1615
 
1616 71 marcel
        if ( WN_operator(src_address) == OPR_LDA &&
1617
          WN_field_id(src_value) != 0 ) {
1618 2 marcel
 
1619
          src_st      = WN_st(src_address);
1620
          src_offset += WN_offset(src_address);
1621 71 marcel
        } else  src_st = NULL;
1622
/*
1623 2 marcel
        if (    WN_operator(src_address) == OPR_ARRAY
1624
             && WN_operator(WN_kid0(src_address)) == OPR_LDA )
1625
          src_st = NULL;
1626
 
1627
        else {
1628
 
1629
          preg = Create_Preg (Pointer_Mtype, vho_lower_mstore_name);
1630
 
1631
          preg_st     = MTYPE_To_PREG ( Pointer_Mtype );
1632
          preg_ty_idx = ptr_src_ty_idx;
1633
 
1634
          if ( src_offset == 0 ) {
1635
 
1636
            opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
1637
            temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx,
1638
           src_address );
1639 71 marcel
          } else {
1640 2 marcel
            opc  = OPCODE_make_op ( OPR_INTCONST, Pointer_Mtype, MTYPE_V );
1641
            temp = WN_CreateIntconst ( opc, src_offset );
1642
            opc  = OPCODE_make_op ( OPR_ADD, Pointer_Mtype, MTYPE_V );
1643
            temp = WN_CreateExp2 ( opc, src_address, temp );
1644
            opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
1645
            temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx, temp );
1646
          }
1647
 
1648
          WN_Set_Linenum(temp, srcpos);
1649
 
1650
          WN_INSERT_BlockAfter ( block, WN_last(block), temp );
1651
 
1652
          opc = OPCODE_make_op ( OPR_LDID, Pointer_Mtype, Pointer_Mtype );
1653
          src_address = WN_CreateLdid ( opc, preg, preg_st, preg_ty_idx );
1654
          src_st      = NULL;
1655
          src_offset  = 0;
1656
        }
1657 71 marcel
*/
1658 2 marcel
 
1659
        dst_offset = WN_store_offset(wn);
1660
 
1661 71 marcel
        if ( WN_operator(dst_address) == OPR_LDA && WN_field_id(wn) == 0) {
1662 2 marcel
 
1663
          dst_st      = WN_st(dst_address);
1664
          dst_offset += WN_offset(dst_address);
1665
        }
1666 71 marcel
        else  dst_st = NULL;
1667
/*
1668 2 marcel
        if (    WN_operator(dst_address) == OPR_ARRAY
1669
             && WN_operator(WN_kid0(dst_address)) == OPR_LDA )
1670
          dst_st = NULL;
1671
 
1672
        else {
1673
 
1674
          preg = Create_Preg (Pointer_Mtype, vho_lower_mstore_name);
1675
 
1676
          preg_st     = MTYPE_To_PREG ( Pointer_Mtype );
1677
          preg_ty_idx = ptr_src_ty_idx;
1678
 
1679
          if ( dst_offset == 0 ) {
1680
 
1681
            opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
1682
            temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx,
1683
           dst_address );
1684
          }
1685
 
1686
          else {
1687
 
1688
            opc  = OPCODE_make_op ( OPR_INTCONST, Pointer_Mtype, MTYPE_V );
1689
            temp = WN_CreateIntconst ( opc, dst_offset );
1690
            opc  = OPCODE_make_op ( OPR_ADD, Pointer_Mtype, MTYPE_V );
1691
            temp = WN_CreateExp2 ( opc, dst_address, temp );
1692
            opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
1693
            temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx, temp );
1694
          }
1695
 
1696
          WN_Set_Linenum(temp, srcpos);
1697
 
1698
          WN_INSERT_BlockAfter ( block, WN_last(block), temp );
1699
 
1700
          opc  = OPCODE_make_op ( OPR_LDID, Pointer_Mtype, Pointer_Mtype );
1701
          dst_address = WN_CreateLdid ( opc, preg, preg_st, preg_ty_idx );
1702
          dst_st      = NULL;
1703
          dst_offset  = 0;
1704
        }
1705 71 marcel
*/
1706
        // field_offset = 0;
1707 2 marcel
 
1708
        for ( i = 0; i < VHO_Struct_Nfields; i++ ) {
1709
 
1710
          TY_IDX   fty_idx;
1711
          WN     * src;
1712
          WN     * dst;
1713
 
1714
          fty_idx = VHO_Struct_Fld_Table [i];
1715
          if ( src_st ) {
1716
            opc = OPCODE_make_op ( OPR_LDID,
1717
                                   Promoted_Mtype [TY_mtype(fty_idx)],
1718
                                   TY_mtype(fty_idx) );
1719 71 marcel
            src = WN_CreateLdid ( opc, src_offset + VHO_Struct_Offset_Table[i],
1720 2 marcel
                                  src_st, fty_idx );
1721
          }
1722
          else {
1723
            opc = OPCODE_make_op ( OPR_ILOAD,
1724
                                   Promoted_Mtype [TY_mtype(fty_idx)],
1725
                                   TY_mtype(fty_idx) );
1726 71 marcel
            src = WN_CreateIload ( opc, src_offset + VHO_Struct_Offset_Table[i], fty_idx,
1727 2 marcel
                                   Make_Pointer_Type ( fty_idx, FALSE ),
1728
                                   WN_COPY_Tree ( src_address ) );
1729
          }
1730
          if ( dst_st ) {
1731
            opc = OPCODE_make_op ( OPR_STID, MTYPE_V, TY_mtype(fty_idx) );
1732 71 marcel
            dst = WN_CreateStid ( opc, dst_offset + VHO_Struct_Offset_Table[i],
1733 2 marcel
                                  dst_st, fty_idx, src );
1734
          }
1735
          else {
1736
            opc = OPCODE_make_op ( OPR_ISTORE, MTYPE_V, TY_mtype(fty_idx) );
1737 71 marcel
            dst = WN_CreateIstore ( opc, dst_offset + VHO_Struct_Offset_Table[i],
1738 2 marcel
                                    Make_Pointer_Type ( fty_idx, FALSE ),
1739
                                    src,
1740
                                    WN_COPY_Tree ( dst_address ) );
1741
          }
1742
          WN_Set_Linenum(dst, srcpos);
1743
          WN_INSERT_BlockAfter ( block, WN_last(block), dst );
1744 71 marcel
          // field_offset += TY_size(fty_idx);
1745 2 marcel
        }
1746
        wn = block;
1747
      }
1748
    }
1749
 
1750
    else {
1751
#ifdef VHO_DEBUG
1752
      if ( VHO_Struct_Debug )
1753
        fprintf ( TFile, "VHO_Lower_Mstore : FALSE %d\n", (INT32) srcpos );
1754
#endif /* VHO_DEBUG */
1755
    }
1756
  }
1757
  return wn;
1758
} /* VHO_Lower_Mstore */
1759
 
1760 1950 laijx
inline BOOL Is_Ldid_Or_Lda (WN *tree)
1761
{
1762
  return (WN_operator(tree) == OPR_LDID || WN_operator(tree) == OPR_LDA);
1763
}
1764
// 64bit code can have cvt above the multiply
1765
inline BOOL Is_Multiply_Or_Cvt_Multiply (WN *tree)
1766
{
1767
  return ((WN_operator(tree) == OPR_MPY)
1768
    || (WN_operator(tree) == OPR_CVT && WN_operator(WN_kid0(tree)) == OPR_MPY));
1769
}
1770
 
1771
// share code for finding LDID under a MMILOAD
1772
static WN*
1773
Find_Ldid_Under_Iload (WN *iload_kid)
1774
{
1775
    if (Is_Ldid_Or_Lda(iload_kid)) {
1776
    return iload_kid;
1777
    }
1778
    else if (WN_operator(iload_kid) == OPR_ADD) {
1779
      if (Is_Ldid_Or_Lda(WN_kid0(iload_kid))
1780
        && Is_Multiply_Or_Cvt_Multiply(WN_kid1(iload_kid)) )
1781
      {
1782
      // array index
1783
      return WN_kid0(iload_kid);
1784
      }
1785
      // check other kid
1786
      else if (Is_Ldid_Or_Lda(WN_kid1(iload_kid))
1787
        && Is_Multiply_Or_Cvt_Multiply(WN_kid0(iload_kid)) )
1788
      {
1789
      // array index
1790
      return WN_kid1(iload_kid);
1791
      }
1792
    }
1793
    else if (WN_operator(iload_kid) == OPR_ARRAY) {
1794
      // recurse on array index variant
1795
      return Find_Ldid_Under_Iload (WN_kid0(iload_kid));
1796
    }
1797
    return NULL;
1798
}
1799
 
1800
static TY_IDX
1801
Is_MM_load(WN *src, WN *dst)
1802
{
1803
  if (WN_opcode(src) == OPC_MMLDID) {
1804
    if (ST_class(WN_st(dst)) != CLASS_PREG &&
1805
       ST_class(WN_st(src)) != CLASS_PREG)
1806
      return WN_ty(src);
1807
    else
1808
      return (TY_IDX)0;
1809
  }
1810
  if (WN_opcode(src) == OPC_MMILOAD) {
1811
    if (OPCODE_is_load(WN_opcode(WN_kid0(src))))
1812
      return WN_ty(WN_kid0(src));
1813
  }
1814
  return (TY_IDX)0;
1815
}
1816
 
1817 71 marcel
/* ==============================================================================
1818
 *
1819
 * WN *VHO_Lower_Mstid(WN * wn)
1820
 *
1821
 * If the structure being copied is sufficiently small, then flatten out the
1822
 * structure into a set of non overlapping fields and load/store the
1823
 * individual fields, thereby replacing MMSTID/MLDID by a sequence of
1824
 * one or more (controlled by VHO_Struct_Limit) pairs of STID/ISTORE
1825
 * over LDID/ILOAD.
1826
 *
1827
 * The following structures are not currently handled.
1828
 *
1829
 * structures containing misaligned fields
1830
 * structures containing bit fields
1831
 * structures containing arrays
1832
 *
1833
 * ==============================================================================
1834
 */
1835 2 marcel
 
1836 71 marcel
WN *
1837
VHO_Lower_Mstid (WN * wn)
1838
{
1839
  WN_OFFSET   dst_offset;
1840
  TY_IDX      dst_ty_idx;
1841
  ST        * dst_st;
1842
  WN        * src_value;
1843 1950 laijx
  WN        * src_iload_kid;
1844
  WN        * src_ldid;
1845 71 marcel
  WN_OFFSET   src_offset;
1846
  TY_IDX      src_ty_idx;
1847 1950 laijx
  TY_IDX      orig_src_ty_idx;
1848
  TY_IDX      src_ptr_ty_idx;
1849 71 marcel
  ST        * src_st;
1850
  WN        * size;
1851
  INT64       bytes;
1852
  WN        * block;
1853
  // WN_OFFSET   field_offset;
1854
  INT32       i;
1855
  SRCPOS      srcpos;
1856
  OPCODE      opc;
1857 1950 laijx
  BOOL        src_is_pointer = FALSE;
1858 2322 dcoakley
  BOOL        ty_mismatch;
1859 1950 laijx
  INT src_field_id = 0;
1860
  INT dst_field_id = 0;
1861 71 marcel
 
1862 2322 dcoakley
  if (VHO_SCL_Debug) {
1863
      fprintf ( TFile, "\nVHO_Lower_Mstid  lowering:\n");
1864
      fdump_tree(TFile, wn);
1865
  }
1866
 
1867 71 marcel
  src_value   = WN_kid0(wn);
1868
  dst_ty_idx  = WN_ty(wn);
1869
  srcpos      = WN_Get_Linenum(wn);
1870
 
1871 1950 laijx
  // field_ids complicate things, as they require generating
1872
  // (struct-type, field_id) rather than a simple field type.
1873
  // We can handle field_ids by getting fty
1874
  // of struct subfields for appropriate mtype, but generating field_ids
1875
  // of original struct for the actual ldid/stid.
1876
  if (WN_field_id(wn) != 0) {
1877
      dst_field_id = WN_field_id(wn);
1878
      dst_ty_idx = get_field_type(dst_ty_idx, WN_field_id(wn));
1879 71 marcel
  }
1880 1950 laijx
  if (WN_opcode(src_value) == OPC_MMLDID) {
1881
      src_ldid = src_value;
1882
      src_ty_idx = WN_ty(src_ldid);
1883
  }
1884
  else if (WN_opcode(src_value) == OPC_MMILOAD)
1885
  {
1886
      // will replace MSTID(MMILOAD) with STID<field1>(ILOAD<field1>),etc
1887
      src_iload_kid = WN_kid0(src_value);
1888
      // is indirect load, so will be pointer type
1889
      src_is_pointer = TRUE;
1890
      src_ptr_ty_idx =  WN_load_addr_ty(src_value);
1891
 
1892
      if (TY_kind(src_ptr_ty_idx) != KIND_POINTER) {
1893
          return wn;      // doesn't fit pattern so ignore
1894
      }
1895
      src_ty_idx = TY_pointed(src_ptr_ty_idx);
1896
      src_ldid = Find_Ldid_Under_Iload (src_iload_kid);
1897
 
1898
      if (src_ldid == NULL)
1899
          return wn;  // don't handle any other cases
1900
  }
1901
  else
1902
  {
1903
      return wn;  // don't handle any other cases
1904
  }
1905
 
1906
  // keep the original src_type
1907
  orig_src_ty_idx = src_ty_idx;
1908
  // we have a src_ty_idx type at src_field_id of orig_src_ty_idx
1909
  if (WN_field_id(src_value) != 0) {
1910
      src_field_id = WN_field_id(src_value);
1911
      src_ty_idx = get_field_type(src_ty_idx, src_field_id);
1912
  }
1913
  // iload of preg is okay cause iload takes the field offset
1914
  if ( ST_class(WN_st(wn)) == CLASS_PREG ||
1915
       (ST_class(WN_st(src_ldid)) == CLASS_PREG && !src_is_pointer)) {
1916
      /* screen out PREG for now, need to change them into extract sometime */
1917
      return wn;
1918
  }
1919
 
1920 71 marcel
  bytes = TY_size(dst_ty_idx);
1921
 
1922 1950 laijx
#if defined(TARG_NVISA)
1923
  if ((VHO_Struct_Opt && (bytes > 0))) {
1924
#else
1925
  if ((VHO_Struct_Opt && (bytes > 0)) && (Is_MM_load(src_value, wn) != (TY_IDX)0)) {
1926
    /* screen out PREG for now, need to change them into extract sometime */
1927
#endif
1928 71 marcel
 
1929 1411 laijx
#ifdef KEY
1930
    VHO_Struct_Nfields = 0;
1931
    VHO_Struct_Can_Be_Lowered = TRUE;
1932
#endif
1933 71 marcel
 
1934 1950 laijx
          // Used to check for matching struct alignment,
1935
          // but we don't need alignment to match to copy fields
1936
          // (may have been related to unused VHO_Struct_Alignment variable).
1937
          // if(   TY_align(src_ty_idx) == TY_align(dst_ty_idx)
1938
    if (TY_kind(src_ty_idx) == KIND_STRUCT
1939 71 marcel
       && TY_is_packed(Ty_Table[src_ty_idx]) == FALSE
1940
       && TY_is_packed(Ty_Table[dst_ty_idx]) == FALSE
1941
       && bytes / TY_align(src_ty_idx) <= VHO_Struct_Limit) {
1942
 
1943 1411 laijx
#ifndef KEY
1944 71 marcel
      VHO_Struct_Nfields = 0;
1945
      VHO_Struct_Can_Be_Lowered = TRUE;
1946 1411 laijx
#endif
1947 71 marcel
      //  VHO_Struct_Alignment = TY_align(dst_ty_idx);
1948
 
1949 1950 laijx
      // Flatten out the structure into non overlapping fields
1950
      // src_field_id is the starting point of type src_ty_idx
1951
      // inside the outer structure of type orig_src_ty_idx
1952
 
1953
      VHO_Get_Field_List (0, src_ty_idx, src_field_id);
1954
 
1955 71 marcel
#ifdef VHO_DEBUG
1956
      if ( VHO_Struct_Debug)
1957
        fprintf ( TFile, "VHO_Lower_Mstid : %s %d \n",
1958
                  VHO_Struct_Can_Be_Lowered ? "TRUE" : "FALSE",
1959
                  (INT32) srcpos);
1960
#endif /* VHO_DEBUG */
1961
 
1962
      if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields) {
1963
 
1964
        block = WN_CreateBlock();
1965
        WN_Set_Linenum (block, srcpos);
1966 1950 laijx
        src_st = WN_st(src_ldid);
1967
        // preserve offset from original ldid/iload
1968 71 marcel
        src_offset = WN_offset(src_value);
1969
        dst_st = WN_st(wn);
1970
        dst_offset = WN_store_offset(wn);
1971
 
1972
        // field_offset = 0;
1973
 
1974
        for (i = 0; i < VHO_Struct_Nfields; i++) {
1975
 
1976
          TY_IDX    fty_idx;
1977
          WN      * src;
1978
          WN      * dst;
1979
 
1980
          fty_idx = VHO_Struct_Fld_Table[i];
1981 1950 laijx
          if (src_is_pointer) {
1982
              opc = OPCODE_make_op ( OPR_ILOAD,
1983
                                     Promoted_Mtype [TY_mtype(fty_idx)],
1984
                                     TY_mtype(fty_idx) );
1985
              if (VHO_Struct_Field_Is_Array_Table[i]) {
1986
                  src = WN_CreateIload ( opc,
1987
                                         src_offset + VHO_Struct_Offset_Table[i],
1988
                                         fty_idx,
1989
                                         Make_Pointer_Type ( fty_idx),
1990
                                         WN_COPY_Tree (src_iload_kid) );
1991
              } else {
1992
                  src = WN_CreateIload ( opc,
1993
                                         src_offset + VHO_Struct_Offset_Table[i],
1994
                                         orig_src_ty_idx, src_ptr_ty_idx,
1995
                                         WN_COPY_Tree (src_iload_kid),
1996
                                         VHO_Struct_Field_Id_Table[i]);
1997
              }
1998
          } else {
1999
              opc = OPCODE_make_op ( OPR_LDID,
2000
                                     Promoted_Mtype [TY_mtype(fty_idx)],
2001
                                     TY_mtype(fty_idx) );
2002
              if (VHO_Struct_Field_Is_Array_Table[i]) {
2003
                  // each element uses same field_id,
2004
                  // so rather than create array refs, just do element copies
2005
                  src = WN_CreateLdid ( opc,
2006
                                        src_offset + VHO_Struct_Offset_Table[i],
2007
                                        src_st, fty_idx);
2008
              } else {
2009
                  src = WN_CreateLdid ( opc,
2010
                                        src_offset + VHO_Struct_Offset_Table[i],
2011
                                        src_st, WN_ty(src_ldid),
2012
                                        VHO_Struct_Field_Id_Table[i]);
2013
              }
2014
          }
2015 2322 dcoakley
 
2016
          // Note (1).  The source and dest. types must match otherwise, the
2017
          // calculation to compute the field_id argument to WN_CreateStid()
2018
          // will be incorrect.
2019 71 marcel
          opc = OPCODE_make_op ( OPR_STID, MTYPE_V, TY_mtype(fty_idx) );
2020 2322 dcoakley
          ty_mismatch = TY_id(src_ty_idx) != TY_id(dst_ty_idx);
2021
          if (VHO_Struct_Field_Is_Array_Table[i] || ty_mismatch || VHO_Disable_Copy_Field_Element) {
2022 1950 laijx
              // each element uses same field_id,
2023
              // so rather than create array refs, just do element copies
2024
              dst = WN_CreateStid ( opc,
2025
                                    dst_offset + VHO_Struct_Offset_Table[i],
2026
                                    dst_st, fty_idx, src);
2027 2322 dcoakley
              if (VHO_M_Debug_Type_Mismatch && ty_mismatch || VHO_SCL_Debug) {
2028
                  fprintf(TFile, "VHO_Lower_Mstid: %stype mismatch, dst WN follows\n",
2029
                        ty_mismatch ? "" : "no ");
2030
                  fdump_tree(TFile, dst);
2031
              }
2032 1950 laijx
          } else {
2033
              dst = WN_CreateStid ( opc,
2034
                                    dst_offset + VHO_Struct_Offset_Table[i],
2035
                                    dst_st, WN_ty(wn), src,
2036
                                    dst_field_id - src_field_id + VHO_Struct_Field_Id_Table[i]);
2037 2322 dcoakley
              if (VHO_SCL_Debug) {
2038
                  fprintf(TFile, "dst_field_id=%d, src_field_id=%d, VHO_Struct_Field_Id_Table[%d]=%d, dst WN follows\n",
2039
                          dst_field_id, src_field_id, i, VHO_Struct_Field_Id_Table[i]);
2040
                  fdump_tree(TFile, dst);
2041
              }
2042 1950 laijx
          }
2043 71 marcel
          WN_Set_Linenum(dst, srcpos);
2044
          WN_INSERT_BlockAfter (block, WN_last(block), dst);
2045
          // field_offset += TY_size(fty_idx);
2046 1950 laijx
        } //end for
2047 71 marcel
        wn = block;
2048 1950 laijx
      } // end if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields) {
2049
    } // end TY_kind(src_ty_idx) == KIND_STRUCT
2050 749 hucheng
#ifdef KEY
2051
    if (VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields)
2052
      ; // we already lowered the struct
2053 1950 laijx
#ifdef TARG_SL
2054
    else if ((bytes == 4) &&  TY_size(src_ty_idx) == bytes) {
2055
#else
2056 749 hucheng
    else if ((bytes == 4 || bytes == 8) && TY_size(src_ty_idx) == bytes) {
2057 1950 laijx
#endif
2058 749 hucheng
      // bug 7741: change MTYPE_M to MTYPE_U[48]
2059
      TYPE_ID mtype = (bytes == 4) ? MTYPE_U4 : MTYPE_U8;
2060
      WN_set_desc(wn, mtype);
2061
      WN_set_rtype(src_value, mtype);
2062
      WN_set_desc(src_value, mtype);
2063 71 marcel
 
2064 749 hucheng
      // bugs 9989, 10139
2065
      INT field_id;
2066 1950 laijx
      // We allow the field_id not zero, comment out the Is_True
2067
      //Is_True (WN_field_id(src_value) == 0,("Expected field-id zero"));
2068 749 hucheng
      if ((TY_kind(src_ty_idx) == KIND_STRUCT) &&
2069
          (field_id /* assign */ = single_field_in_struct (src_ty_idx)))
2070
        WN_set_field_id (src_value, field_id);
2071
 
2072 1950 laijx
      // We allow the field_id not zero, comment out the Is_True
2073
      //Is_True (WN_field_id(wn) == 0,("Expected field-id zero"));
2074 749 hucheng
      if ((TY_kind(dst_ty_idx) == KIND_STRUCT) &&
2075
          (field_id /* assign */ = single_field_in_struct (dst_ty_idx)))
2076
        WN_set_field_id (wn, field_id);
2077
    }
2078
    else {
2079
#endif
2080
 
2081 71 marcel
#ifdef VHO_DEBUG
2082
    if ( VHO_Struct_Debug)
2083
     fprintf (TFile, "VHO_Lower_Mstid: FALSE %d\n", (INT32) scrpos);
2084
#endif /* VHO_DEBUG */
2085
    }
2086
  }
2087
  return wn;
2088
} /* VHO_Lower_Mstid */
2089
 
2090
/* ============================================================================
2091
 *
2092
 * WN *VHO_Lower_Mistore ( WN * wn )
2093
 *
2094
 * If the structure being copied is sufficiently small, then flatten out the
2095
 * structure into a set of non overlapping fields and load/istore the
2096
 * individual fields, thereby replacing MISTORE/MLDID by a sequence of
2097
 * one or more (controlled by VHO_Struct_Limit) pairs of STID/ISTORE
2098
 * over LDID/ILOAD.
2099
 *
2100
 * The following structures are not currently handled.
2101
 *
2102
 *   structures containing misaligned fields
2103
 *   structures containing bit fields
2104
 *   structures containing arrays
2105
 *
2106
 * ============================================================================
2107
 */
2108 1950 laijx
 
2109 71 marcel
WN *
2110
VHO_Lower_Mistore ( WN * wn )
2111
{
2112
  WN_OFFSET   dst_offset;
2113
  TY_IDX      dst_ty_idx;
2114
  ST        * dst_st;
2115
  WN        * src_value;
2116
  WN_OFFSET   src_offset;
2117
  TY_IDX      src_ty_idx;
2118
  ST        * src_st;
2119
  WN        * size;
2120
  INT64       bytes;
2121
  WN        * block;
2122 2322 dcoakley
  BOOL        ty_mismatch;
2123 71 marcel
  // WN_OFFSET   field_offset;
2124
  INT32       i;
2125
  SRCPOS      srcpos;
2126
  OPCODE      opc;
2127 1950 laijx
  INT src_field_id = 0;
2128
  INT dst_field_id = 0;
2129
  BOOL src_is_pointer = FALSE;
2130
  TY_IDX src_ptr_ty_idx;
2131
  WN *src_iload_kid;
2132
  WN *src_ldid;
2133 71 marcel
 
2134 2322 dcoakley
  if (VHO_SCL_Debug) {
2135
      fprintf ( TFile, "\nVHO_Lower_Mistore lowering:\n");
2136
      fdump_tree(TFile, wn);
2137
  }
2138 71 marcel
  src_value      = WN_kid0(wn);
2139
  WN *dst_address= WN_kid1(wn);
2140
  dst_offset     = WN_store_offset(wn);
2141
  TY_IDX ptr_dst_ty_idx = WN_ty(wn);
2142
  dst_ty_idx     = TY_pointed(Ty_Table[ptr_dst_ty_idx]);
2143
  if (WN_field_id(wn) != 0) {
2144
    dst_ty_idx = get_field_type(dst_ty_idx, WN_field_id(wn));
2145
  }
2146
  srcpos         = WN_Get_Linenum(wn);
2147
  bytes          = TY_size(dst_ty_idx);
2148
 
2149
  if (WN_field_id(src_value) != 0) {
2150
    /* otherwise, we need to get to the subfields, or generate ILOAD, later */
2151
    return wn;
2152
  }
2153 1950 laijx
  if ( VHO_Struct_Opt
2154
    && bytes > 0) {
2155
    if (WN_opcode(src_value) == OPC_MMLDID
2156
    && ST_class(WN_st(src_value)) != CLASS_PREG ) {
2157
      /* screen out PREG for now, need to change them into extract sometime */
2158
      src_ty_idx     = WN_ty(src_value);
2159
      src_ldid = src_value;
2160
    }
2161
    else if (WN_opcode(src_value) == OPC_MMILOAD) {
2162
      // is indirect load, so will be pointer type
2163
      src_is_pointer = TRUE;
2164
      src_ptr_ty_idx =  WN_load_addr_ty(src_value);
2165
      if (TY_kind(src_ptr_ty_idx) != KIND_POINTER) {
2166
        return wn;      // doesn't fit pattern so ignore
2167
      }
2168
      src_ty_idx = TY_pointed(src_ptr_ty_idx);
2169
      src_iload_kid = WN_kid0(src_value);
2170
      src_ldid = Find_Ldid_Under_Iload (src_iload_kid);
2171
      if (src_ldid == NULL)
2172
        return wn;// don't handle other cases
2173
    }
2174
    else {
2175
      return wn; // don't handle other cases
2176
    }
2177
 
2178
    // Used to check for matching struct alignment,
2179
    // but we don't need alignment to match to copy fields
2180
    // (may have been related to unused VHO_Struct_Alignment variable).
2181
    // if (    TY_align(src_ty_idx) == TY_align(dst_ty_idx)
2182
    if (TY_kind(src_ty_idx) == KIND_STRUCT
2183
          && TY_is_packed(Ty_Table[src_ty_idx]) == FALSE
2184
          && TY_is_packed(Ty_Table[dst_ty_idx]) == FALSE
2185
          && bytes / TY_align(src_ty_idx) <= VHO_Struct_Limit ) {
2186 71 marcel
 
2187
      VHO_Struct_Nfields = 0;
2188
      VHO_Struct_Can_Be_Lowered = TRUE;
2189
      //    VHO_Struct_Alignment = TY_align(dst_ty_idx);
2190
      /* Flatten out the structure into non overlapping fields */
2191 1950 laijx
      VHO_Get_Field_List ( 0, src_ty_idx, WN_field_id(src_value) );
2192 71 marcel
 
2193
#ifdef VHO_DEBUG
2194
      if ( VHO_Struct_Debug )
2195
        fprintf ( TFile, "VHO_Lower_Mistore : %s %d\n",
2196 1950 laijx
                    VHO_Struct_Can_Be_Lowered ? "TRUE" : "FALSE",
2197
                    (INT32) srcpos );
2198 71 marcel
#endif /* VHO_DEBUG */
2199
 
2200
      if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields ) {
2201
 
2202
        block = WN_CreateBlock ();
2203
        WN_Set_Linenum ( block, srcpos );
2204 1950 laijx
        src_st     = WN_st(src_ldid);
2205 71 marcel
 
2206 1950 laijx
        // preserve offset from original ldid/iload
2207 71 marcel
        src_offset = WN_offset(src_value);
2208
        // field_offset = 0;
2209
        for ( i = 0; i < VHO_Struct_Nfields; i++ ) {
2210
 
2211
          TY_IDX   fty_idx;
2212
          WN     * src;
2213
          WN     * dst;
2214
 
2215
          fty_idx = VHO_Struct_Fld_Table [i];
2216
 
2217 1950 laijx
          if (src_is_pointer) {
2218
            opc = OPCODE_make_op ( OPR_ILOAD,
2219
                                   Promoted_Mtype [TY_mtype(fty_idx)],
2220
                                   TY_mtype(fty_idx) );
2221
            if (VHO_Struct_Field_Is_Array_Table[i]) {
2222
              src = WN_CreateIload ( opc,
2223
                                     src_offset + VHO_Struct_Offset_Table[i],
2224
                                     fty_idx,
2225
                                     Make_Pointer_Type ( fty_idx),
2226
                                     WN_COPY_Tree (src_iload_kid) );
2227
            } else {
2228
              src = WN_CreateIload ( opc,
2229
                                     src_offset + VHO_Struct_Offset_Table[i],
2230
                                     src_ty_idx, src_ptr_ty_idx,
2231
                                     WN_COPY_Tree (src_iload_kid),
2232
                                     VHO_Struct_Field_Id_Table[i]);
2233
      }
2234
          }
2235
          else {
2236
            opc = OPCODE_make_op ( OPR_LDID,
2237
                                   Promoted_Mtype [TY_mtype(fty_idx)],
2238
                                   TY_mtype(fty_idx) );
2239
            if (VHO_Struct_Field_Is_Array_Table[i]) {
2240
              // each element uses same field_id,
2241
              // so rather than create array refs, just do element copies
2242
              src = WN_CreateLdid ( opc,
2243
                                    src_offset + VHO_Struct_Offset_Table[i],
2244
                                    src_st, fty_idx );
2245
            } else {
2246
              src = WN_CreateLdid ( opc,
2247
                                    src_offset + VHO_Struct_Offset_Table[i],
2248
                                    src_st, src_ty_idx, VHO_Struct_Field_Id_Table[i]);
2249
            }
2250
          }
2251
          opc = OPCODE_make_op ( OPR_ISTORE, MTYPE_V, TY_mtype(fty_idx));
2252 2322 dcoakley
          // See Note (1).
2253
          ty_mismatch = TY_id(src_ty_idx) != TY_id(dst_ty_idx);
2254
          if (VHO_Struct_Field_Is_Array_Table[i] || ty_mismatch || VHO_Disable_Copy_Field_Element) {
2255 1950 laijx
            dst = WN_CreateIstore ( opc,
2256
                                    dst_offset + VHO_Struct_Offset_Table[i],
2257
                                    Make_Pointer_Type( fty_idx),
2258
                                    src, WN_COPY_Tree( dst_address ));
2259 2322 dcoakley
            if (VHO_M_Debug_Type_Mismatch && ty_mismatch || VHO_SCL_Debug) {
2260
              fprintf(TFile, "VHO_Lower_Mistore: %stype mismatch, dst WN follows\n",
2261
                      ty_mismatch ? "" : "no ");
2262
              fdump_tree(TFile, dst);
2263
            }
2264 1950 laijx
          } else {
2265
            dst = WN_CreateIstore ( opc,
2266
                                    dst_offset + VHO_Struct_Offset_Table[i],
2267
                                    ptr_dst_ty_idx,
2268
                                    src, WN_COPY_Tree( dst_address ),
2269
                                    dst_field_id - src_field_id + VHO_Struct_Field_Id_Table[i]);
2270 2322 dcoakley
            if (VHO_SCL_Debug) {
2271
              fprintf(TFile, "dst_field_id=%d, src_field_id=%d, VHO_Struct_Field_Id_Table[%d]=%d, dst WN follows\n",
2272
                      dst_field_id, src_field_id, i, VHO_Struct_Field_Id_Table[i]);
2273
              fdump_tree(TFile, dst);
2274
            }
2275 1950 laijx
          }
2276 71 marcel
          WN_Set_Linenum(dst, srcpos);
2277
 
2278
          WN_INSERT_BlockAfter ( block, WN_last(block), dst );
2279
          // field_offset += TY_size(fty_idx);
2280
        }
2281
        wn = block;
2282
      }
2283
    }
2284
    else {
2285
#ifdef VHO_DEBUG
2286
      if ( VHO_Struct_Debug )
2287
        fprintf ( TFile, "VHO_Lower_Mstid : FALSE %d\n", (INT32) srcpos );
2288
#endif /* VHO_DEBUG */
2289
    }
2290
  }
2291
 
2292
  return wn;
2293 1950 laijx
} /* VHO_Lower_Mistore */
2294 71 marcel
 
2295 2 marcel
static void
2296
vho_lower_set_st_addr_info ( WN * wn, ADDRESS_INFO_TYPE code )
2297
{
2298
  OPCODE     opc;
2299
  OPERATOR   wn_operator;
2300
  ST       * st;
2301
 
2302
  opc = WN_opcode(wn);
2303
  wn_operator = OPCODE_operator(opc);
2304
 
2305
  switch ( wn_operator ) {
2306
 
2307
    case OPR_LDA:
2308
 
2309
      st = WN_st(wn);
2310
      if ( ST_class(st) == CLASS_VAR || ST_class(st) == CLASS_FUNC ) {
2311
 
2312
        if ( code == ADDRESS_PASSED ) {
2313
 
2314
          if ( WHIRL_Addr_Passed_On ) {
2315
            Set_ST_addr_taken_passed(st);
2316
 
2317
            if ( WHIRL_Addr_Saved_For_Passed_On )
2318
              Set_ST_addr_taken_saved(st);
2319
          }
2320
        }
2321
 
2322
        else
2323
          Set_ST_addr_taken_saved(st);
2324
      }
2325
      break;
2326
 
2327
    case OPR_ARRAY:
2328
 
2329
      vho_lower_set_st_addr_info ( WN_kid0(wn), code );
2330
      break;
2331
 
2332
    case OPR_LDID:
2333
/*
2334
      st = WN_st(wn);
2335
      if ( ST_sclass(st) == SCLASS_FORMAL && (ST_class(st) == CLASS_VAR ||
2336
                ST_class(st) == CLASS_FUNC ))
2337
        if ( code == ADDRESS_PASSED )
2338
          Set_ST_addr_taken_passed(st);
2339
        else
2340
          Set_ST_addr_taken_saved(st);
2341
      break;
2342
*/
2343
    case OPR_CONST:
2344
    case OPR_ILOAD:
2345
    case OPR_MLOAD:
2346
    case OPR_INTCONST:
2347
    case OPR_INTRINSIC_OP:
2348
    case OPR_CALL:
2349
    case OPR_EQ:
2350
    case OPR_NE:
2351
    case OPR_GT:
2352
    case OPR_GE:
2353
    case OPR_LT:
2354
    case OPR_LE:
2355
      break;
2356
 
2357
    case OPR_EVAL:
2358
    case OPR_TAS:
2359
    case OPR_CVT:
2360
    case OPR_CVTL:
2361
    case OPR_NEG:
2362
    case OPR_ABS:
2363
    case OPR_SQRT:
2364
    case OPR_REALPART:
2365
    case OPR_IMAGPART:
2366
    case OPR_PAREN:
2367
    case OPR_RND:
2368
    case OPR_TRUNC:
2369
    case OPR_CEIL:
2370
    case OPR_FLOOR:
2371
    case OPR_BNOT:
2372
    case OPR_LNOT:
2373
    case OPR_DIVPART:
2374
    case OPR_REMPART:
2375
    case OPR_MINPART:
2376
    case OPR_MAXPART:
2377
    case OPR_RECIP:
2378
    case OPR_RSQRT:
2379
    case OPR_PARM:
2380
 
2381
      vho_lower_set_st_addr_info ( WN_kid0(wn), code );
2382
      break;
2383
 
2384
    case OPR_SELECT:
2385
    case OPR_CSELECT:
2386
    case OPR_ADD:
2387
    case OPR_SUB:
2388
    case OPR_MPY:
2389
    case OPR_DIV:
2390
    case OPR_MOD:
2391
    case OPR_REM:
2392
    case OPR_DIVREM:
2393
    case OPR_MAX:
2394
    case OPR_MIN:
2395
    case OPR_MINMAX:
2396
    case OPR_BAND:
2397
    case OPR_BIOR:
2398
    case OPR_BXOR:
2399
    case OPR_BNOR:
2400
    case OPR_LAND:
2401
    case OPR_LIOR:
2402
    case OPR_SHL:
2403
    case OPR_ASHR:
2404
    case OPR_LSHR:
2405
    case OPR_COMPLEX:
2406
    case OPR_HIGHMPY:
2407 71 marcel
#ifdef KEY
2408
    case OPR_COMPOSE_BITS:
2409
#endif
2410 2 marcel
 
2411
      vho_lower_set_st_addr_info ( WN_kid0(wn), code );
2412
      vho_lower_set_st_addr_info ( WN_kid1(wn), code );
2413
      break;
2414
 
2415
    case OPR_CAND:
2416
    case OPR_CIOR:
2417
 
2418
      break;
2419
 
2420
    case OPR_COMMA:
2421
 
2422
      vho_lower_set_st_addr_info ( WN_kid1(wn), code );
2423
      break;
2424
 
2425
    case OPR_RCOMMA:
2426
 
2427
      vho_lower_set_st_addr_info ( WN_kid0(wn), code );
2428
      break;
2429
 
2430
    default:
2431
 
2432
      FmtAssert ( TRUE,
2433
                  ("vho_lower_set_st_addr_info not implemented") );
2434
  }
2435
} /* vho_lower_set_st_addr_taken */
2436
 
2437
 
2438
static void
2439
vho_initialize_bool_info ( BOOL_INFO * bool_info )
2440
{
2441
  bool_info->opcode           = OPCODE_UNKNOWN;
2442
  bool_info->used_true_label  = FALSE;
2443
  bool_info->used_false_label = FALSE;
2444
  bool_info->true_label       = 0;
2445
  bool_info->false_label      = 0;
2446
} /* vho_initialize_bool_info */
2447
 
2448
 
2449
static WN *
2450 1950 laijx
vho_lower_comma ( WN * wn, WN *block, BOOL_INFO * bool_info, BOOL is_return=FALSE)
2451 2 marcel
{
2452
  WN       * comma_block;
2453
  WN       * result_block;
2454
  WN       * result;
2455
  WN       * first;
2456
  WN       * value;
2457
  WN       * stmt;
2458 1537 laijx
  WN       * prev_call;
2459 2 marcel
  PREG_NUM   preg;
2460
  BOOL       call;
2461
 
2462
  result = WN_kid1 (wn);
2463 1537 laijx
  if( PU_cxx_lang (Get_Current_PU()) && WN_operator(WN_last(WN_kid0(wn))) == OPR_STID)
2464
    prev_call = WN_kid0(WN_last(WN_kid0(wn)));
2465
  else
2466
    prev_call = NULL;
2467 2 marcel
  call   =   WHIRL_Return_Val_On
2468
          && WN_operator(result) == OPR_LDID
2469
          && WN_st(result) == Return_Val_Preg;
2470
 
2471 1537 laijx
  if ( PU_cxx_lang (Get_Current_PU())&&
2472
       prev_call &&
2473
       WN_operator(prev_call) == OPR_LDID &&
2474
       (WN_st(prev_call) == Return_Val_Preg || is_return)&&
2475
       WN_rtype(prev_call) == MTYPE_M &&
2476
       WN_rtype(wn) == MTYPE_M){
2477
    WN_Set_Linenum ( block, VHO_Srcpos );
2478
    WN * next_wn;
2479
 
2480 1950 laijx
    for ( wn = WN_first( WN_kid0(wn)); wn; wn = next_wn ) {
2481 1537 laijx
      next_wn = WN_next(wn);
2482
      if (!next_wn) {
2483
  result = vho_lower_expr (WN_kid0(wn), block, bool_info);
2484
  break;
2485
      }
2486
      wn = vho_lower ( wn, block );
2487
      if ( wn )
2488
  WN_INSERT_BlockLast ( block, wn );
2489
    }
2490 1950 laijx
    return result;
2491 1537 laijx
  }
2492
 
2493 2 marcel
  comma_block = vho_lower_block (WN_kid0(wn));
2494
  WN_Set_Linenum ( comma_block, VHO_Srcpos );
2495
  first = WN_first(comma_block);
2496
 
2497
  result_block = WN_CreateBlock ();
2498
  result = vho_lower_expr (WN_kid1(wn), result_block, bool_info);
2499
 
2500
  if (    VHO_Call_Opt
2501
       && first
2502
       && WN_first(result_block) == NULL
2503
       && WN_operator(first) == OPR_PRAGMA
2504
       && WN_pragma(first) == WN_PRAGMA_INLINE_BODY_START ) {
2505
/*
2506
    fprintf ( stderr, "INLINE_BODY_START\n" );
2507
    fdump_tree ( stderr, comma_block );
2508
*/
2509
    value = NULL;
2510
    preg  = 0;
2511
 
2512
    stmt = WN_next(first);
2513
 
2514
    for (;;) {
2515
/*
2516
      fprintf ( stderr, "INLINE stmt\n" );
2517
      fdump_tree ( stderr, stmt );
2518
*/
2519
      if (    WN_operator(stmt) == OPR_STID
2520
           && ST_class(WN_st(stmt)) == CLASS_PREG ) {
2521
 
2522
        if ( value == NULL )
2523
          value = WN_kid0(stmt);
2524
 
2525
        else
2526
        if (    WN_operator(WN_kid0(stmt)) == OPR_LDID
2527
             && ST_class(WN_st(WN_kid0(stmt))) == CLASS_PREG
2528
             && WN_load_offset(WN_kid0(stmt)) == preg ) {
2529
        }
2530
 
2531
        else
2532
          break;
2533
 
2534
        preg = WN_store_offset(stmt);
2535
/*
2536
        fprintf ( stderr, "preg = %d\n", preg );
2537
*/
2538
      }
2539
 
2540
      else
2541
      if (    WN_operator(stmt) == OPR_PRAGMA
2542
           && WN_pragma(stmt) == WN_PRAGMA_INLINE_BODY_END ) {
2543
 
2544
        stmt = WN_next(stmt);
2545
/*
2546
        fprintf ( stderr, "INLINE_BODY_END\n" );
2547
        fprintf ( stderr, "result\n" );
2548
        fdump_tree ( stderr, result );
2549
        fprintf ( stderr, "stmt\n" );
2550
        fdump_tree ( stderr, stmt );
2551
*/
2552
        if (    stmt
2553
             && WN_next(stmt) == NULL
2554
             && WN_operator(stmt) == OPR_STID
2555
             && ST_class(WN_st(stmt)) == CLASS_PREG ) {
2556
 
2557
          if ( value == NULL )
2558
            value = WN_kid0(stmt);
2559
 
2560
          else
2561
          if (    WN_operator(WN_kid0(stmt)) == OPR_LDID
2562
               && ST_class(WN_st(WN_kid0(stmt))) == CLASS_PREG
2563
               && WN_load_offset(WN_kid0(stmt)) == preg ) {
2564
          }
2565
 
2566
          else
2567
            break;
2568
        }
2569
 
2570
        else
2571
          break;
2572
 
2573
        preg = WN_store_offset(stmt);
2574
/*
2575
        fprintf ( stderr, "preg = %d\n", preg );
2576
        fprintf ( stderr, "value\n" );
2577
        fdump_tree ( stderr, value );
2578
        fprintf ( stderr, "preg = %d\n", preg );
2579
*/
2580
        if (    value
2581
             && WN_operator(result) == OPR_LDID
2582
             && ST_class(WN_st(result)) == CLASS_PREG
2583
             && WN_load_offset(result) == preg ) {
2584
 
2585
          comma_block = NULL;
2586
          result = WN_Simplify_Tree ( value );
2587
/*
2588
          fprintf ( stderr, "vho_lower_comma: inline old\n" );
2589
          fdump_tree ( stderr, wn );
2590
          fprintf ( stderr, "vho_lower_comma: inline new\n" );
2591
          fdump_tree ( stderr, result );
2592
*/
2593
        }
2594
 
2595
        break;
2596
      }
2597
 
2598
      else
2599
        break;
2600
 
2601
      stmt = WN_next(stmt);
2602
    }
2603
  }
2604
 
2605
  if ( comma_block ) {
2606
 
2607
    if (call) {
2608
 
2609
      TYPE_ID rtype  = WN_rtype (result);
2610
      TYPE_ID desc   = WN_desc  (result);
2611
      TY_IDX  ty_idx = WN_ty (result);
2612
 
2613
      if (desc == MTYPE_M) {
2614
 
2615
        ST* st = Gen_Temp_Symbol (ty_idx, ".call");
2616
        wn = WN_CreateStid (OPC_MSTID, 0, st, ty_idx, result);
2617
        WN_Set_Linenum ( wn, VHO_Srcpos );
2618
        WN_INSERT_BlockLast (comma_block, wn);
2619
        result = WN_CreateLdid (OPC_MMLDID, 0, st, ty_idx);
2620
      }
2621 71 marcel
#ifdef TARG_X8664
2622 1411 laijx
      else if (MTYPE_is_complex(desc) ||
2623 1950 laijx
               MTYPE_is_mmx_vector(desc)) {
2624
        ST* st = Gen_Temp_Symbol (ty_idx, ".call");
2625 83 marcel
        wn = WN_CreateStid (OPR_STID, MTYPE_V, desc, 0, st, ty_idx, result);
2626 71 marcel
        WN_Set_Linenum ( wn, VHO_Srcpos );
2627
        WN_INSERT_BlockLast (comma_block, wn);
2628 83 marcel
        result = WN_CreateLdid (OPR_LDID, desc, desc, 0, st, ty_idx);
2629 71 marcel
      }
2630
#endif
2631 2 marcel
 
2632
      else {
2633
 
2634 135 marcel
#ifdef KEY
2635
  if (VHO_In_MP_Region_Pragma)
2636
  { // Use a temporary symbol instead of a preg
2637
    ST * comma_st = Gen_Temp_Symbol (MTYPE_TO_TY_array[rtype], "_comma");
2638
    wn = WN_Stid (rtype, 0, comma_st, ty_idx, result);
2639
          WN_Set_Linenum ( wn, VHO_Srcpos );
2640
          WN_INSERT_BlockLast (comma_block, wn);
2641
    result = WN_Ldid (rtype, 0, comma_st, ty_idx);
2642
  }
2643
  else
2644
#endif // KEY
2645
  {
2646
          PREG_NUM preg    = Create_Preg (rtype, vho_lower_comma_name);
2647
          ST*      preg_st = MTYPE_To_PREG (rtype);
2648
          OPCODE   opcode  = OPCODE_make_op (OPR_STID, MTYPE_V, rtype);
2649
          wn = WN_CreateStid (opcode, preg, preg_st, ty_idx, result);
2650
          WN_Set_Linenum ( wn, VHO_Srcpos );
2651
          WN_INSERT_BlockLast (comma_block, wn);
2652
          opcode = OPCODE_make_op (OPR_LDID, rtype, rtype);
2653
          result = WN_CreateLdid (opcode, preg, preg_st, ty_idx);
2654
  }
2655 2 marcel
      }
2656
    }
2657
 
2658 135 marcel
#ifdef KEY
2659
    if (VHO_In_MP_Region_Pragma && WN_operator (result) == OPR_LDID &&
2660
        ST_class (WN_st (result)) == CLASS_PREG)
2661
    {
2662
      // This can be caused by inlining of a call inside an xpragma, where
2663
      // we need to use a temporary instead of a preg.
2664
      TYPE_ID rtype = WN_rtype (result);
2665
      ST * comma_st = Gen_Temp_Symbol (MTYPE_TO_TY_array[rtype], "_comma");
2666
      WN * stid = WN_Stid (rtype, 0, comma_st, WN_ty (result), result);
2667
      WN_Set_Linenum (stid, VHO_Srcpos);
2668
      WN_INSERT_BlockLast (comma_block, stid);
2669
      result = WN_Ldid (rtype, 0, comma_st, WN_ty (result));
2670
    }
2671
 
2672
    // If this comma node is inside an atomic pragma, insert the lowered
2673
    // comma block before the pragma node, since omp-lowerer expects the
2674
    // atomic store to be the next stmt after the pragma
2675
    WN * last = WN_last (block);
2676
    if (last && WN_operator (last) == OPR_PRAGMA &&
2677
        WN_pragma (last) == WN_PRAGMA_ATOMIC)
2678
    {
2679
      WN_INSERT_BlockBefore ( block, WN_last (block), comma_block );
2680
    }
2681
    else
2682
#endif // KEY
2683
      WN_INSERT_BlockLast ( block, comma_block );
2684 2 marcel
  }
2685
 
2686
  if ( WN_first(result_block) ) {
2687
 
2688
    WN_INSERT_BlockLast ( block, result_block );
2689
  }
2690
 
2691
  wn = result;
2692
 
2693
  return wn;
2694
} /* vho_lower_comma */
2695
 
2696
 
2697
static WN *
2698
vho_lower_rcomma ( WN * wn, WN *block, BOOL_INFO * bool_info )
2699
{
2700
  WN       * rcomma_block;
2701
  WN       * test;
2702
  TYPE_ID    preg_mtype;
2703
  PREG_NUM   preg;
2704
  ST       * preg_st;
2705
  TY_IDX     preg_ty_idx;
2706
  OPCODE     opcode;
2707
 
2708
  preg_mtype = WN_rtype(wn);
2709
  rcomma_block = WN_CreateBlock ();
2710
  WN_Set_Linenum ( rcomma_block, VHO_Srcpos );
2711
 
2712
  test         = vho_lower_expr (WN_kid0(wn), rcomma_block, bool_info);
2713
  if ( WN_first(rcomma_block) )
2714
    WN_INSERT_BlockLast ( block, rcomma_block );
2715
  rcomma_block = vho_lower_block ( WN_kid1(wn));
2716
 
2717
  preg = Create_Preg (preg_mtype, vho_lower_rcomma_name);
2718
 
2719
  preg_st      = MTYPE_To_PREG ( preg_mtype );
2720
  preg_ty_idx  = Be_Type_Tbl(preg_mtype);
2721
  opcode       = OPCODE_make_op ( OPR_STID, MTYPE_V, preg_mtype );
2722
  wn           = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, test );
2723
  WN_Set_Linenum ( wn, VHO_Srcpos );
2724
 
2725
  WN_INSERT_BlockLast ( block, wn  );
2726
  WN_INSERT_BlockLast ( block, rcomma_block );
2727
  opcode     = OPCODE_make_op ( OPR_LDID, Promoted_Mtype [preg_mtype],
2728
                                preg_mtype );
2729
  wn = WN_CreateLdid ( opcode, preg, preg_st, preg_ty_idx );
2730
 
2731
  return wn;
2732
} /* vho_lower_rcomma */
2733
 
2734
 
2735
static WN *
2736
vho_simplify_cand ( WN * wn, WN * l_wn, WN * r_wn )
2737
{
2738
  BOOL       simplified;
2739
  OPCODE     l_opc;
2740
  OPCODE     r_opc;
2741
  OPERATOR   l_oper;
2742
  OPERATOR   r_oper;
2743
  OPERATOR   ll_oper;
2744
  OPERATOR   lr_oper;
2745
  OPERATOR   rl_oper;
2746
  OPERATOR   rr_oper;
2747
  OPERATOR   llr_oper;
2748
  OPERATOR   rlr_oper;
2749
 
2750
  WN       * ll_wn;
2751
  WN       * lr_wn;
2752
  WN       * rl_wn;
2753
  WN       * rr_wn;
2754
  WN       * lll_wn;
2755
  WN       * llr_wn;
2756
  WN       * rll_wn;
2757
  WN       * rlr_wn;
2758
 
2759
  simplified = FALSE;
2760
 
2761
  l_opc  = WN_opcode(l_wn);
2762
  r_opc  = WN_opcode(r_wn);
2763
  l_oper = OPCODE_operator(l_opc);
2764
  r_oper = OPCODE_operator(r_opc);
2765
 
2766
  /* simplify
2767
   *          ( e && e )
2768
   * to
2769
   *          ( e )
2770
   */
2771
 
2772
  if ( WN_Simp_Compare_Trees ( l_wn, r_wn ) == 0 ) {
2773
 
2774
    wn = l_wn;
2775
    simplified = TRUE;
2776
  }
2777
 
2778
  /* simplify
2779
   *          ( e && TRUE )
2780
   * to
2781
   *          ( e )
2782
   */
2783
 
2784
  else
2785
  if (    r_oper == OPR_INTCONST
2786
       && WN_const_val(r_wn) == 1 ) {
2787
 
2788
    wn = l_wn;
2789
    simplified = TRUE;
2790
  }
2791
 
2792
  /* simplify
2793
   *          ( e && FALSE )
2794
   * to
2795
   *          ( FALSE )
2796
   */
2797
 
2798
  else
2799
  if (    r_oper == OPR_INTCONST
2800
       && WN_const_val(r_wn) == 0 ) {
2801
 
2802
    wn = r_wn;
2803
    simplified = TRUE;
2804
  }
2805
 
2806
  /* simplify
2807
   *          ( TRUE && e )
2808
   * to
2809
   *          ( e )
2810
   */
2811
 
2812
  else
2813
  if (    l_oper == OPR_INTCONST
2814
       && WN_const_val(l_wn) == 1 ) {
2815
 
2816
    wn = r_wn;
2817
    simplified = TRUE;
2818
  }
2819
 
2820
  /* simplify
2821
   *          ( FALSE && e )
2822
   * to
2823
   *          ( FALSE )
2824
   */
2825
 
2826
  else
2827
  if (    l_oper == OPR_INTCONST
2828
       && WN_const_val(l_wn) == 0 ) {
2829
 
2830
    wn = l_wn;
2831
    simplified = TRUE;
2832
  }
2833
 
2834
  /* simplify
2835
   *           ( ( e1 || e2 ) && ( e1 || e3 ) )
2836
   * to
2837
   *           ( e1 || ( e2 && e3 ) )
2838
   */
2839
 
2840
  else
2841
  if (    l_oper == OPR_CIOR
2842
       && r_oper == OPR_CIOR ) {
2843
 
2844
    ll_wn   = WN_kid0(l_wn);
2845
    lr_wn   = WN_kid1(l_wn);
2846
    rl_wn   = WN_kid0(r_wn);
2847
    rr_wn   = WN_kid1(r_wn);
2848
 
2849
    if ( WN_Simp_Compare_Trees ( ll_wn, rl_wn ) == 0 ) {
2850
 
2851
      WN *r_wn_new = WN_Create ( OPC_I4CAND, 2 );
2852
      WN_kid0(r_wn_new) = lr_wn;
2853
      WN_kid1(r_wn_new) = rr_wn;
2854
      wn = WN_Create ( OPC_I4CIOR, 2 );
2855
      WN_kid0(wn) = ll_wn;
2856
      WN_kid1(wn) = r_wn_new;
2857
      simplified = TRUE;
2858
 
2859
      if ( Cur_PU_Feedback )
2860
  Cur_PU_Feedback->FB_factor_circuit( l_wn, r_wn, wn, r_wn_new );
2861
    }
2862
  }
2863
 
2864
  /* simplify
2865
   *          ( ( ( e & c1 ) != 0 ) && ( ( e & c2 ) != 0 ) )
2866
   * to
2867
   *          ( ( e & ( c1 | c2 ) ) == ( c1 | c2 ) )
2868
   */
2869
 
2870
  else
2871
  if (    l_oper == OPR_NE
2872
       && r_oper == OPR_NE
2873
       && l_opc  == r_opc ) {
2874
 
2875
    ll_wn   = WN_kid0(l_wn);
2876
    lr_wn   = WN_kid1(l_wn);
2877
    rl_wn   = WN_kid0(r_wn);
2878
    rr_wn   = WN_kid1(r_wn);
2879
 
2880
    ll_oper = WN_operator(ll_wn);
2881
    lr_oper = WN_operator(lr_wn);
2882
    rl_oper = WN_operator(rl_wn);
2883
    rr_oper = WN_operator(rr_wn);
2884
 
2885
    if (    ll_oper == OPR_BAND
2886
         && lr_oper == OPR_INTCONST
2887
         && WN_const_val(lr_wn) == 0
2888
         && rl_oper == OPR_BAND
2889
         && rr_oper == OPR_INTCONST
2890
         && WN_const_val(rr_wn) == 0 ) {
2891
 
2892
       lll_wn = WN_kid0(ll_wn);
2893
       llr_wn = WN_kid1(ll_wn);
2894
       rll_wn = WN_kid0(rl_wn);
2895
       rlr_wn = WN_kid1(rl_wn);
2896
 
2897
       llr_oper = WN_operator(llr_wn);
2898
       rlr_oper = WN_operator(rlr_wn);
2899
 
2900
       if (    llr_oper == OPR_INTCONST
2901
            && rlr_oper == OPR_INTCONST
2902
            && WN_Simp_Compare_Trees ( lll_wn, rll_wn ) == 0
2903
            && IS_POWER_OF_2(WN_const_val(llr_wn))
2904
            && IS_POWER_OF_2(WN_const_val(rlr_wn)) ) {
2905
 
2906
         r_wn = rlr_wn;
2907
         WN_const_val(r_wn) |= WN_const_val(llr_wn);
2908
         ll_wn = lll_wn;
2909
         lr_wn = llr_wn;
2910
         WN_const_val(lr_wn) = WN_const_val(r_wn);
2911
         l_wn = WN_CreateExp2 ( WN_opcode(rl_wn), ll_wn, lr_wn );
2912 83 marcel
#ifdef KEY
2913
   if( MTYPE_is_size_double(WN_rtype(l_wn)) )
2914
     wn = WN_CreateExp2 ( OPC_I4I8EQ, l_wn, r_wn );
2915
   else
2916
#endif
2917
     wn = WN_CreateExp2 ( OPC_I4I4EQ, l_wn, r_wn );
2918 2 marcel
         simplified = TRUE;
2919
       }
2920
    }
2921
  }
2922
 
2923
  if ( ! simplified ) {
2924
 
2925
    if (    WN_kid0(wn) != l_wn
2926
         || WN_kid1(wn) != r_wn ) {
2927
 
2928
      wn = WN_Create ( OPC_I4CAND, 2 );
2929
      WN_kid0(wn) = l_wn;
2930
      WN_kid1(wn) = r_wn;
2931
    }
2932
  }
2933
 
2934
  return wn;
2935
} /* vho_simplify_cand */
2936
 
2937
static WN *
2938
vho_simplify_cior ( WN * wn, WN * l_wn, WN * r_wn )
2939
{
2940
  BOOL       simplified;
2941
  OPCODE     l_opc;
2942
  OPCODE     r_opc;
2943
  OPERATOR   l_oper;
2944
  OPERATOR   r_oper;
2945
  OPERATOR   ll_oper;
2946
  OPERATOR   lr_oper;
2947
  OPERATOR   rl_oper;
2948
  OPERATOR   rr_oper;
2949
  OPERATOR   llr_oper;
2950
  OPERATOR   rlr_oper;
2951
 
2952
  WN       * ll_wn;
2953
  WN       * lr_wn;
2954
  WN       * rl_wn;
2955
  WN       * rr_wn;
2956
  WN       * lll_wn;
2957
  WN       * llr_wn;
2958
  WN       * rll_wn;
2959
  WN       * rlr_wn;
2960
 
2961
  simplified = FALSE;
2962
 
2963
  l_opc  = WN_opcode(l_wn);
2964
  r_opc  = WN_opcode(r_wn);
2965
  l_oper = OPCODE_operator(l_opc);
2966
  r_oper = OPCODE_operator(r_opc);
2967
 
2968
  if ( WN_Simp_Compare_Trees ( l_wn, r_wn ) == 0 ) {
2969
 
2970
    wn = l_wn;
2971
    simplified = TRUE;
2972
  }
2973
 
2974
  /* simplify
2975
   *          ( e || TRUE )
2976
   * to
2977
   *          ( TRUE )
2978
   */
2979
 
2980
  else
2981
  if (    r_oper == OPR_INTCONST
2982
       && WN_const_val(r_wn) == 1 ) {
2983
 
2984
    wn = r_wn;
2985
    simplified = TRUE;
2986
  }
2987
 
2988
  /* simplify
2989
   *          ( e && FALSE )
2990
   * to
2991
   *          ( e )
2992
   */
2993
 
2994
  else
2995
  if (    r_oper == OPR_INTCONST
2996
       && WN_const_val(r_wn) == 0 ) {
2997
 
2998
    wn = l_wn;
2999
    simplified = TRUE;
3000
  }
3001
 
3002
  /* simplify
3003
   *          ( TRUE || e )
3004
   * to
3005
   *          ( TRUE )
3006
   */
3007
 
3008
  else
3009
  if (    l_oper == OPR_INTCONST
3010
       && WN_const_val(l_wn) == 1 ) {
3011
 
3012
    wn = l_wn;
3013
    simplified = TRUE;
3014
  }
3015
 
3016
  /* simplify
3017
   *          ( FALSE || e )
3018
   * to
3019
   *          ( e )
3020
   */
3021
 
3022
  else
3023
  if (    l_oper == OPR_INTCONST
3024
       && WN_const_val(l_wn) == 0 ) {
3025
 
3026
    wn = r_wn;
3027
    simplified = TRUE;
3028
  }
3029
 
3030
  /* simplify
3031
   *           ( ( e1 && e2 ) || ( e1 && e3 ) )
3032
   * to
3033
   *           ( e1 && ( e2 || e3 ) )
3034
   */
3035
 
3036
  else
3037
  if (    l_oper == OPR_CAND
3038
       && r_oper == OPR_CAND ) {
3039
 
3040
    ll_wn   = WN_kid0(l_wn);
3041
    lr_wn   = WN_kid1(l_wn);
3042
    rl_wn   = WN_kid0(r_wn);
3043
    rr_wn   = WN_kid1(r_wn);
3044
 
3045
    if ( WN_Simp_Compare_Trees ( ll_wn, rl_wn ) == 0 ) {
3046
 
3047
      WN *r_wn_new = WN_Create ( OPC_I4CIOR, 2 );
3048
      WN_kid0(r_wn_new) = lr_wn;
3049
      WN_kid1(r_wn_new) = rr_wn;
3050
      wn = WN_Create ( OPC_I4CAND, 2 );
3051
      WN_kid0(wn) = ll_wn;
3052
      WN_kid1(wn) = r_wn_new;
3053
      simplified = TRUE;
3054
 
3055
      if ( Cur_PU_Feedback )
3056
  Cur_PU_Feedback->FB_factor_circuit( l_wn, r_wn, wn, r_wn_new );
3057
    }
3058
  }
3059
 
3060
  /* simplify
3061
   *          ( ( ( e & c1 ) != 0 ) || ( ( e & c2 ) != 0 ) )
3062
   * to
3063
   *          ( e & ( c1 | c2 ) )
3064
   */
3065
 
3066
  else
3067
  if (    l_oper == OPR_NE
3068
       && r_oper == OPR_NE
3069
       && l_opc  == r_opc ) {
3070
 
3071
    ll_wn   = WN_kid0(l_wn);
3072
    lr_wn   = WN_kid1(l_wn);
3073
    rl_wn   = WN_kid0(r_wn);
3074
    rr_wn   = WN_kid1(r_wn);
3075
 
3076
    ll_oper = WN_operator(ll_wn);
3077
    lr_oper = WN_operator(lr_wn);
3078
    rl_oper = WN_operator(rl_wn);
3079
    rr_oper = WN_operator(rr_wn);
3080
 
3081
    if (    ll_oper == OPR_BAND
3082
         && lr_oper == OPR_INTCONST
3083
         && WN_const_val(lr_wn) == 0
3084
         && rl_oper == OPR_BAND
3085
         && rr_oper == OPR_INTCONST
3086
         && WN_const_val(rr_wn) == 0 ) {
3087
 
3088
      lll_wn = WN_kid0(ll_wn);
3089
      llr_wn = WN_kid1(ll_wn);
3090
      rll_wn = WN_kid0(rl_wn);
3091
      rlr_wn = WN_kid1(rl_wn);
3092
 
3093
      llr_oper = WN_operator(llr_wn);
3094
      rlr_oper = WN_operator(rlr_wn);
3095
 
3096
      if (    llr_oper == OPR_INTCONST
3097
           && rlr_oper == OPR_INTCONST
3098
           && WN_Simp_Compare_Trees ( lll_wn, rll_wn ) == 0 ) {
3099
 
3100
        ll_wn = lll_wn;
3101
        lr_wn = llr_wn;
3102
        WN_const_val(lr_wn) |= WN_const_val(rlr_wn);
3103
        l_wn = WN_CreateExp2 ( WN_opcode(rl_wn), ll_wn, lr_wn );
3104
        r_wn = rr_wn;
3105
        wn = WN_CreateExp2 ( l_opc, l_wn, r_wn );
3106
        simplified = TRUE;
3107
      }
3108
    }
3109
  }
3110
 
3111
  if ( ! simplified ) {
3112
 
3113
    if (    WN_kid0(wn) != l_wn
3114
         || WN_kid1(wn) != r_wn ) {
3115
 
3116
      wn = WN_Create ( OPC_I4CIOR, 2 );
3117
      WN_kid0(wn) = l_wn;
3118
      WN_kid1(wn) = r_wn;
3119
    }
3120
  }
3121
 
3122
  return wn;
3123
} /* vho_simplify_cior */
3124
 
3125
 
3126
static WN *
3127
vho_simplify_cand_cior ( WN * wn )
3128
{
3129
  WN * lwn;
3130
  WN * rwn;
3131
 
3132
  switch ( WN_opcode(wn) ) {
3133
 
3134
// >> WHIRL 0.30: replaced OPC_CAND by OPC_B and OPC_I4 variants
3135
// TODO WHIRL 0.30: get rid of OPC_I4 variant
3136
    case OPC_BCAND:
3137
    case OPC_I4CAND:
3138
// << WHIRL 0.30: replaced OPC_CAND by OPC_B and OPC_I4 variants
3139
 
3140
      lwn = vho_simplify_cand_cior ( WN_kid0(wn) );
3141
      rwn = vho_simplify_cand_cior ( WN_kid1(wn) );
3142
      wn  = vho_simplify_cand ( wn, lwn, rwn );
3143
      break;
3144
 
3145
// >> WHIRL 0.30: replaced OPC_CIOR by OPC_B and OPC_I4 variants
3146
// TODO WHIRL 0.30: get rid of OPC_I4 variant
3147
    case OPC_BCIOR:
3148
    case OPC_I4CIOR:
3149
// << WHIRL 0.30: replaced OPC_CIOR by OPC_B and OPC_I4 variants
3150
 
3151
      lwn = vho_simplify_cand_cior ( WN_kid0(wn) );
3152
      rwn = vho_simplify_cand_cior ( WN_kid1(wn) );
3153
      wn  = vho_simplify_cior ( wn, lwn, rwn );
3154
      break;
3155
  }
3156
 
3157
  return wn;
3158
} /* vho_simplify_cand_cior */
3159
 
3160
 
3161
static WN *
3162
vho_lower_cand_cior ( WN *wn, WN *block, BOOL_INFO *bool_info )
3163
{
3164
  WN        * one;
3165
  WN        * zero;
3166
  WN        * cflow_block1;
3167
  WN        * cflow_block2;
3168
  BOOL_INFO   cflow_bool_info;
3169
  BOOL_INFO   cflow_bool_info1;
3170
  BOOL_INFO   cflow_bool_info2;
3171
  OPCODE      opcode;
3172
  LABEL_IDX   join_label;
3173
  WN        * lwn;
3174
  WN        * rwn;
3175
  PREG_NUM    preg;
3176
  ST        * preg_st;
3177
  TY_IDX      preg_ty_idx;
3178
 
3179
  opcode = WN_opcode(wn);
3180
 
3181
  cflow_block1 = WN_CreateBlock ();
3182
  cflow_block2 = WN_CreateBlock ();
3183
 
3184
  WN_Set_Linenum ( cflow_block1, VHO_Srcpos );
3185
  WN_Set_Linenum ( cflow_block2, VHO_Srcpos );
3186
 
3187
  if ( ! bool_info ) {
3188
 
3189
    vho_initialize_bool_info (&cflow_bool_info);
3190
    LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.true_label),
3191
  0, LKIND_DEFAULT);
3192
    LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.false_label),
3193
  0, LKIND_DEFAULT);
3194
    bool_info = &cflow_bool_info;
3195
  }
3196
 
3197
  cflow_bool_info1 = *bool_info;
3198
  cflow_bool_info1.opcode = opcode;
3199
 
3200
  if ( cflow_bool_info1.opcode != OPCODE_UNKNOWN )
3201
    cflow_bool_info1.opcode = opcode;
3202
 
3203
  cflow_bool_info2 = cflow_bool_info1;
3204
 
3205
/*
3206
  if (    bool_info->opcode != OPCODE_UNKNOWN
3207
       && bool_info->opcode != opcode ) {
3208
*/
3209
 
3210
  {
3211
 
3212
    if ( opcode == (OPC_I4CAND) ) {
3213
 
3214
      LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info1.true_label),
3215
  0, LKIND_DEFAULT);
3216
      cflow_bool_info1.used_true_label  = FALSE;
3217
    }
3218
 
3219
    else {
3220
 
3221
      LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info1.false_label),
3222
  0, LKIND_DEFAULT);
3223
      cflow_bool_info1.used_false_label = FALSE;
3224
    }
3225
  }
3226
 
3227
  lwn = vho_lower_expr (WN_kid0(wn), cflow_block1, &cflow_bool_info1);
3228
  rwn = vho_lower_expr (WN_kid1(wn), cflow_block2, &cflow_bool_info2);
3229
  WN_kid0(wn) = lwn;
3230
  WN_kid1(wn) = rwn;
3231
 
3232
  WN *wn_label, *wn_left_branch = NULL, *wn_right_branch = NULL;
3233
 
3234
  if ( WN_first(cflow_block1) )
3235
    WN_INSERT_BlockLast ( block, cflow_block1 );
3236
 
3237
  if (    WN_first(cflow_block2)
3238
       || cflow_bool_info1.used_true_label
3239
       || cflow_bool_info1.used_false_label
3240
       || cflow_bool_info2.used_true_label
3241
       || cflow_bool_info2.used_false_label ) {
3242
 
3243
    if ( opcode == (OPC_I4CAND) ) {
3244
 
3245
      if ( lwn ) {
3246
 
3247
        wn_left_branch
3248
    = WN_CreateFalsebr ( cflow_bool_info1.false_label, lwn );
3249
        WN_Set_Linenum ( wn_left_branch, VHO_Srcpos );
3250
        WN_INSERT_BlockLast ( block, wn_left_branch );
3251
      }
3252
/*
3253
      else
3254
      if ( cflow_bool_info1.used_true_label ) {
3255
 
3256
        WN *wn_goto = WN_CreateGoto ( (ST_IDX) NULL,
3257
                                      cflow_bool_info1.false_label );
3258
        WN_Set_Linenum ( wn_goto, VHO_Srcpos );
3259
        WN_INSERT_BlockLast ( block, wn_goto );
3260
      }
3261
*/
3262
      if ( cflow_bool_info1.used_true_label ) {
3263
 
3264
        wn_label = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info1.true_label,
3265
            0, NULL );
3266
        WN_Set_Linenum ( wn_label, VHO_Srcpos );
3267
        WN_INSERT_BlockLast ( block, wn_label );
3268
      }
3269
 
3270
      if ( WN_first(cflow_block2) )
3271
        WN_INSERT_BlockLast ( block, cflow_block2 );
3272
 
3273
      if ( rwn ) {
3274
 
3275
        wn_right_branch
3276
    = WN_CreateFalsebr ( cflow_bool_info2.false_label, rwn );
3277
        WN_Set_Linenum ( wn_right_branch, VHO_Srcpos );
3278
        WN_INSERT_BlockLast ( block, wn_right_branch );
3279
 
3280
        if ( bool_info->opcode ) {
3281
 
3282
          if ( opcode != bool_info->opcode ) {
3283
 
3284
            WN *wn_goto
3285
        = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info2.true_label );
3286
            WN_Set_Linenum ( wn_goto, VHO_Srcpos );
3287
            WN_INSERT_BlockLast ( block, wn_goto );
3288
 
3289
            cflow_bool_info2.used_true_label = TRUE;
3290
          }
3291
        }
3292
      }
3293
 
3294
      bool_info->used_false_label = TRUE;
3295
      bool_info->used_true_label |= cflow_bool_info2.used_true_label;
3296
 
3297
      if (Cur_PU_Feedback) {
3298
  Cur_PU_Feedback->FB_lower_circuit( wn,
3299
             wn_left_branch, wn_right_branch );
3300
      }
3301
    }
3302
 
3303
    else {
3304
 
3305
      if ( lwn ) {
3306
 
3307
        wn_left_branch = WN_CreateTruebr ( cflow_bool_info1.true_label, lwn );
3308
        WN_Set_Linenum ( wn_left_branch, VHO_Srcpos );
3309
        WN_INSERT_BlockLast ( block, wn_left_branch );
3310
      }
3311
 
3312
      else
3313
      if ( cflow_bool_info1.used_false_label ) {
3314
 
3315
        WN *wn_goto
3316
    = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info1.true_label );
3317
        WN_Set_Linenum ( wn_goto, VHO_Srcpos );
3318
        WN_INSERT_BlockLast ( block, wn_goto );
3319
      }
3320
 
3321
      if ( cflow_bool_info1.used_false_label ) {
3322
 
3323
        wn_label
3324
    = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info1.false_label, 0, NULL );
3325
        WN_Set_Linenum ( wn_label, VHO_Srcpos );
3326
        WN_INSERT_BlockLast ( block, wn_label );
3327
      }
3328
 
3329
      if ( WN_first(cflow_block2) )
3330
        WN_INSERT_BlockLast ( block, cflow_block2 );
3331
 
3332
      if ( rwn ) {
3333
 
3334
  wn_right_branch
3335
    = WN_CreateFalsebr ( cflow_bool_info2.false_label, rwn );
3336
  WN_Set_Linenum ( wn_right_branch, VHO_Srcpos );
3337
  WN_INSERT_BlockLast ( block, wn_right_branch );
3338
  cflow_bool_info2.used_false_label = TRUE;
3339
 
3340
        if ( bool_info->opcode != opcode
3341
       && bool_info->opcode != OPCODE_UNKNOWN ) {
3342
 
3343
    WN *wn_goto
3344
      = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info2.true_label );
3345
    WN_Set_Linenum ( wn_goto, VHO_Srcpos );
3346
    WN_INSERT_BlockLast ( block, wn_goto );
3347
        }
3348
      }
3349
/*
3350
      else
3351
      if (    bool_info->opcode != opcode
3352
           && bool_info->opcode != OPCODE_UNKNOWN ) {
3353
 
3354
  WN *wn_goto
3355
    = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info2.false_label );
3356
        WN_Set_Linenum ( wn_goto, VHO_Srcpos );
3357
        WN_INSERT_BlockLast ( block, wn_goto );
3358
        cflow_bool_info2.used_false_label = TRUE;
3359
      }
3360
*/
3361
      bool_info->used_true_label   = TRUE;
3362
      bool_info->used_false_label |= cflow_bool_info2.used_false_label;
3363
 
3364
      if (Cur_PU_Feedback)
3365
  Cur_PU_Feedback->FB_lower_circuit( wn,
3366
             wn_left_branch, wn_right_branch );
3367
    }
3368
 
3369
    if ( bool_info == &cflow_bool_info ) {
3370
 
3371
      // TODO: Frequency data for the following
3372
 
3373
      LABEL_Init (New_LABEL (CURRENT_SYMTAB, join_label),
3374
  0, LKIND_DEFAULT);
3375
 
3376
      preg = Create_Preg (MTYPE_I4, vho_lower_cand_cior_name);
3377
 
3378
      preg_st     = MTYPE_To_PREG ( MTYPE_I4 );
3379
      preg_ty_idx = Be_Type_Tbl(MTYPE_I4);
3380
 
3381
      if ( bool_info->used_true_label ) {
3382
 
3383
        wn = WN_CreateLabel ( (ST_IDX) 0, bool_info->true_label, 0, NULL );
3384
        WN_Set_Linenum ( wn, VHO_Srcpos );
3385
        WN_INSERT_BlockLast ( block, wn );
3386
      }
3387
 
3388
      one = WN_CreateIntconst ( OPC_I4INTCONST, 1 );
3389
      wn  = WN_CreateStid ( OPC_I4STID, preg, preg_st, preg_ty_idx, one );
3390
      WN_Set_Linenum ( wn, VHO_Srcpos );
3391
      WN_INSERT_BlockLast ( block, wn );
3392
 
3393
      wn = WN_CreateGoto ( (ST_IDX) NULL, join_label );
3394
      WN_Set_Linenum ( wn, VHO_Srcpos );
3395
      WN_INSERT_BlockLast ( block, wn );
3396
 
3397
      wn = WN_CreateLabel ( (ST_IDX) 0, bool_info->false_label, 0, NULL );
3398
      WN_Set_Linenum ( wn, VHO_Srcpos );
3399
      WN_INSERT_BlockLast ( block, wn );
3400
 
3401
      zero    = WN_CreateIntconst ( OPC_I4INTCONST, 0 );
3402
      wn      = WN_CreateStid ( OPC_I4STID, preg, preg_st, preg_ty_idx, zero );
3403
      WN_Set_Linenum ( wn, VHO_Srcpos );
3404
      WN_INSERT_BlockLast ( block, wn );
3405
 
3406
      wn = WN_CreateLabel ( (ST_IDX) 0, join_label, 0, NULL );
3407
      WN_Set_Linenum ( wn, VHO_Srcpos );
3408
      WN_INSERT_BlockLast ( block, wn );
3409
 
3410
      wn      = WN_CreateLdid ( OPC_I4I4LDID, preg, preg_st, preg_ty_idx );
3411
    }
3412
 
3413
    else
3414
 
3415
      wn = NULL;
3416
  }
3417
 
3418
  else {
3419
 
3420
    wn = vho_simplify_cand_cior ( wn );
3421
  }
3422
 
3423
  return wn;
3424
} /* vho_lower_cand_cior */
3425
 
3426
 
3427
static WN *
3428
vho_lower_cselect ( WN * wn_cselect, WN * block, BOOL_INFO * bool_info )
3429
{
3430
  WN        * wn = wn_cselect;
3431
  WN        * cflow_block;
3432
  WN        * cflow_block1;
3433
  WN        * cflow_block2;
3434
  BOOL_INFO   cflow_bool_info;
3435
  WN        * test;
3436
  WN        * lwn;
3437
  WN        * rwn;
3438
  TYPE_ID     preg_mtype;
3439
  PREG_NUM    preg;
3440
  ST        * preg_st;
3441
  TY_IDX      preg_ty_idx;
3442
  OPCODE      opcode;
3443
  OPCODE      addopc;
3444
  OPCODE      intopc;
3445
  LABEL_IDX   join_label;
3446
  BOOL        mcselect;
3447
  BOOL        vcselect;
3448
  TY_IDX      ty_idx;
3449
  WN_OFFSET   offset;
3450
  WN_OFFSET   lwn_offset;
3451
  WN_OFFSET   rwn_offset;
3452
  WN        * swn;
3453
  BOOL        has_side_effects;
3454
 
3455
  vcselect     = FALSE;
3456
  mcselect     = FALSE;
3457
  cflow_block  = WN_CreateBlock ();
3458
  cflow_block1 = WN_CreateBlock ();
3459
  cflow_block2 = WN_CreateBlock ();
3460
 
3461
  WN_Set_Linenum ( cflow_block,  VHO_Srcpos );
3462
  WN_Set_Linenum ( cflow_block1, VHO_Srcpos );
3463
  WN_Set_Linenum ( cflow_block2, VHO_Srcpos );
3464
 
3465
  vho_initialize_bool_info (&cflow_bool_info);
3466
 
3467
  LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.true_label),
3468
  0, LKIND_DEFAULT);
3469
  LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.false_label),
3470
  0, LKIND_DEFAULT);
3471
 
3472
  opcode = WN_opcode(wn_cselect);
3473
  test   = vho_lower_expr ( WN_kid0(wn_cselect), cflow_block,
3474
          &cflow_bool_info );
3475
  lwn    = vho_lower_expr ( WN_kid1(wn_cselect), cflow_block1, NULL );
3476
  rwn    = vho_lower_expr ( WN_kid2(wn_cselect), cflow_block2, NULL );
3477
 
3478 1950 laijx
  if (    WHIRL_Mldid_Mstid_On && opcode == OPC_MCSELECT && test != NULL ) {
3479 2 marcel
 
3480
    // CSELECT                             IF
3481
    //  <test>                              <test>
3482
    //  <then_expr>                        THEN
3483
    //  <else_expr>            ===>          <then_expr>
3484
    //                                      STID <preg>
3485
    //                                     ELSE
3486
    //                                       <else_expr>
3487
    //                                      STID <preg>
3488
    //                                     END_IF
3489
 
3490
    ty_idx = WN_ty(lwn);
3491 135 marcel
#ifdef KEY // bug 5179
3492
    if (WN_field_id(lwn) != 0)
3493
      ty_idx = get_field_type(ty_idx, WN_field_id(lwn));
3494
#endif
3495 2 marcel
    ST* temp = Gen_Temp_Symbol (ty_idx, ".mcselect");
3496
 
3497
    wn = WN_CreateStid (OPR_STID, MTYPE_V, MTYPE_M,
3498
                        0, ST_st_idx (temp), ty_idx, lwn);
3499
    WN_Set_Linenum (wn, VHO_Srcpos);
3500
    WN_INSERT_BlockLast (cflow_block1, wn);
3501
 
3502
    wn = WN_CreateStid (OPR_STID, MTYPE_V, MTYPE_M,
3503
                        0, ST_st_idx (temp), ty_idx, rwn);
3504
    WN_Set_Linenum (wn, VHO_Srcpos);
3505
    WN_INSERT_BlockLast (cflow_block2, wn);
3506
 
3507
    wn = WN_CreateIf (test, cflow_block1, cflow_block2);
3508
    WN_Set_Linenum ( wn, VHO_Srcpos );
3509
    if ( Cur_PU_Feedback ) {
3510
      Cur_PU_Feedback->FB_lower_branch( wn_cselect, wn );
3511
    }
3512
 
3513
    if (WN_first (cflow_block))
3514
      WN_INSERT_BlockLast (block, cflow_block);
3515
 
3516
    WN_INSERT_BlockLast (block, wn);
3517
 
3518
    wn = WN_CreateLdid (OPR_LDID, MTYPE_M, MTYPE_M,
3519
                        0, ST_st_idx (temp), ty_idx);
3520
    return wn;
3521
  }
3522
 
3523
  if (    VHO_Cselect_Opt
3524
       && WN_first(cflow_block) == NULL
3525
       && WN_first(cflow_block1) == NULL
3526
       && WN_first(cflow_block2) == NULL
3527
       && cflow_bool_info.used_true_label == FALSE
3528
       && cflow_bool_info.used_false_label == FALSE ) {
3529
 
3530
    if ( opcode == OPC_VCSELECT ) {
3531
 
3532
    }
3533
 
3534
    else
3535
    if ( opcode == OPC_MCSELECT ) {
3536
 
3537
    }
3538
 
3539
    else {
3540
 
3541
      has_side_effects =    VHO_WN_has_side_effects ( test )
3542
                         || VHO_WN_has_side_effects ( lwn )
3543
                         || VHO_WN_has_side_effects ( rwn );
3544
 
3545
      if ( has_side_effects == FALSE ) {
3546
 
3547 135 marcel
        /* kt != 0 ? kt : 0 => kt */
3548
#ifdef KEY // bug 5363 and bug 5817
3549
        if ( ( ! MTYPE_is_float(WN_desc(test)) || ! Force_IEEE_Comparisons) &&
3550
       WN_operator(test) == OPR_NE &&
3551
       VHO_WN_is_zero(WN_kid1(test)) &&
3552
       WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0 &&
3553
       VHO_WN_is_zero(rwn) )
3554
          return lwn;
3555
#endif
3556 2 marcel
 
3557 1950 laijx
#ifdef KEY
3558 71 marcel
  /* (a-b) >= 0 ? (a-b) : (b-a) => abs(a-b) */
3559
        if( ( WN_operator(test) == OPR_GT ||
3560
        WN_operator(test) == OPR_GE ) &&
3561
      VHO_WN_is_zero(WN_kid1(test))   &&
3562
      WN_Simp_Compare_Trees( WN_kid0(test), lwn ) == 0 ){
3563
 
3564
    if( WN_operator(rwn) == OPR_SUB          &&
3565
        WN_operator(lwn) == WN_operator(rwn) &&
3566
        WN_Simp_Compare_Trees( WN_kid0(rwn), WN_kid1(lwn) ) == 0 &&
3567
        WN_Simp_Compare_Trees( WN_kid1(rwn), WN_kid0(lwn) ) == 0 ){
3568
 
3569
      opcode = OPCODE_make_op ( OPR_ABS,
3570
              WN_rtype(wn),
3571
              MTYPE_V );
3572
      wn = WN_CreateExp1 ( opcode, lwn );
3573
      return wn;
3574
    }
3575
  }
3576
 
3577
  /* Handle saturation arithmetic SUB operator by converting it
3578
   * to an intrinsic
3579
   * x =  (y >= 0x8000) ? y - 0x8000 : 0;
3580
   */
3581 2111 shenruifen
#if defined(TARG_X8664)
3582 71 marcel
  if ( WN_operator(test) == OPR_GT &&
3583
       WN_rtype(test) == MTYPE_I4 &&
3584
       WN_desc(test) == MTYPE_U4 &&
3585
       WN_operator(WN_kid1(test)) == OPR_INTCONST &&
3586
       WN_const_val(WN_kid1(test)) == 0x7fff &&
3587
 
3588
       WN_operator(WN_kid2(wn_cselect)) == OPR_INTCONST &&
3589
       WN_const_val(WN_kid2(wn_cselect)) == 0 &&
3590
 
3591
       WN_operator(WN_kid1(wn_cselect)) == OPR_CVTL &&
3592
       WN_cvtl_bits(WN_kid1(wn_cselect)) == 16 &&
3593
       WN_operator(WN_kid0(WN_kid1(wn_cselect))) == OPR_SUB &&
3594
       WN_operator(WN_kid1(WN_kid0(WN_kid1(wn_cselect)))) ==
3595
       OPR_INTCONST &&
3596
       WN_const_val(WN_kid1(WN_kid0(WN_kid1(wn_cselect)))) == 0x8000 &&
3597
 
3598
       WN_has_sym(WN_kid0(test)) &&
3599
       WN_has_sym(WN_kid0(WN_kid0(WN_kid1(wn_cselect)))) &&
3600
       WN_st(WN_kid0(test)) ==
3601
       WN_st(WN_kid0(WN_kid0(WN_kid1(wn_cselect)))) ) {
3602
    WN* kids[2];
3603
    kids[0] = WN_kid0(test);
3604
    kids[1] = WN_kid1(WN_kid0(WN_kid1(wn_cselect)));
3605
    // Create parm nodes for intrinsic op
3606
    kids[0] = WN_CreateParm (MTYPE_U4, kids[0],
3607
           Be_Type_Tbl(MTYPE_U4),
3608
             WN_PARM_BY_VALUE);
3609
    kids[1] = WN_CreateParm (MTYPE_U4, kids[1],
3610
           Be_Type_Tbl(MTYPE_U4),
3611
             WN_PARM_BY_VALUE);
3612
    wn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP,
3613
              MTYPE_U4, MTYPE_V),
3614
           INTRN_SUBSU2, 2, kids);
3615
    return wn;
3616
 
3617
  }
3618 2111 shenruifen
#endif // TARG_X7664
3619 71 marcel
#endif
3620
 
3621 2 marcel
        /* x > 0 ? x : -x => abs(x) */
3622
 
3623
        if (    (    WN_operator(test) == OPR_GT
3624
                  || WN_operator(test) == OPR_GE )
3625
             && VHO_WN_is_zero(WN_kid1(test))
3626
             && WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0
3627
             && WN_operator(rwn) == OPR_NEG
3628
             && WN_Simp_Compare_Trees ( lwn, WN_kid0(rwn) ) == 0 ) {
3629
 
3630 71 marcel
          DevWarn ( "%s: %s %s\n",
3631 2 marcel
                    OPCODE_name(WN_opcode(wn)),
3632
                    MTYPE_name(WN_rtype(wn)),
3633
                    MTYPE_name(WN_desc(wn)) );
3634
 
3635
          if ( MTYPE_signed(WN_rtype(wn)) ) {
3636
 
3637
            opcode = OPCODE_make_op ( OPR_ABS,
3638
                                      WN_rtype(wn),
3639
                                      MTYPE_V );
3640
            wn = WN_CreateExp1 ( opcode, lwn );
3641 71 marcel
/*
3642 2 marcel
            fdump_tree ( stderr, wn );
3643 71 marcel
*/
3644 2 marcel
            return wn;
3645
          }
3646
        }
3647
 
3648
        /* x >= y ? x : y => max(x) */
3649
 
3650
        if (    (    WN_operator(test) == OPR_GT
3651
                  || WN_operator(test) == OPR_GE )
3652
             && WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0
3653 2111 shenruifen
             && WN_Simp_Compare_Trees ( WN_kid1(test), rwn ) == 0
3654
#if defined(TARG_SL)
3655
             && MTYPE_is_integral(WN_desc(test))
3656
#endif
3657
   ) {
3658 2 marcel
 
3659 71 marcel
          DevWarn ( "%s: %s %s\n",
3660 2 marcel
                    OPCODE_name(WN_opcode(wn)),
3661
                    MTYPE_name(WN_rtype(wn)),
3662
                    MTYPE_name(WN_desc(wn)) );
3663
 
3664
          opcode = OPCODE_make_op ( OPR_MAX,
3665
                                    WN_rtype(wn),
3666
                                    MTYPE_V );
3667
          wn = WN_CreateExp2 ( opcode, lwn, rwn );
3668 71 marcel
/*
3669 2 marcel
          fdump_tree ( stderr, wn );
3670 71 marcel
*/
3671 2 marcel
          return wn;
3672
        }
3673
 
3674
        /* x <= y ? x : y => min(x) */
3675
 
3676
        if (    (    WN_operator(test) == OPR_LT
3677
                  || WN_operator(test) == OPR_LE )
3678
             && WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0
3679 2111 shenruifen
             && WN_Simp_Compare_Trees ( WN_kid1(test), rwn ) == 0
3680
#if defined(TARG_SL)
3681
             && MTYPE_is_integral(WN_desc(test))
3682
#endif
3683
   ) {
3684 2 marcel
 
3685 71 marcel
          DevWarn ( "%s: %s %s\n",
3686 2 marcel
                    OPCODE_name(WN_opcode(wn)),
3687
                    MTYPE_name(WN_rtype(wn)),
3688
                    MTYPE_name(WN_desc(wn)) );
3689
 
3690
          opcode = OPCODE_make_op ( OPR_MIN,
3691
                                    WN_rtype(wn),
3692
                                    MTYPE_V );
3693
          wn = WN_CreateExp2 ( opcode, lwn, rwn );
3694 71 marcel
/*
3695 2 marcel
          fdump_tree ( stderr, wn );
3696 71 marcel
*/
3697 2 marcel
          return wn;
3698
        }
3699 1950 laijx
#ifdef TARG_NVISA
3700
        // gcc converts x += (y == 0) into a cond of x+1 or x.
3701
        // Would be more efficient for us if generated straight line code
3702
        // of t = (y == 0); x += t;
3703
        // Rather than try to change what gcc generates,
3704
        // instead look for x and x+-1 in operands,
3705
        // then transform that back to above 2-stmt sequence.
3706
        if (WN_operator(rwn) == OPR_LDID
3707
              && WN_operator(lwn) == OPR_ADD
3708
              && WN_Simp_Compare_Trees ( WN_kid0(lwn), rwn ) == 0
3709
              && WN_operator(WN_kid1(lwn)) == OPR_INTCONST
3710
              && (WN_const_val(WN_kid1(lwn)) == 1
3711
              // either adding or subtracting the condition result
3712
              || WN_const_val(WN_kid1(lwn)) == -1))
3713
        {
3714
          DevWarn("transform cselect back to straightline code");
3715
          ST *st = Gen_Temp_Symbol (MTYPE_To_TY(WN_rtype(test)), "_cond");
3716
          wn = WN_Stid (WN_rtype(test), 0, st, ST_type(st),
3717
                        test, 0);
3718
          WN_Set_Linenum ( wn, VHO_Srcpos );
3719
          WN_INSERT_BlockLast ( block, wn );
3720
 
3721
          WN *ldid = WN_Ldid (WN_rtype(test), 0, st, ST_type(st));
3722
          if (WN_rtype(test) != WN_rtype(rwn))
3723
            ldid = WN_Cvt(WN_rtype(test), WN_rtype(rwn), ldid);
3724
          if (WN_const_val(WN_kid1(lwn)) == 1)
3725
            wn = WN_Binary(OPR_ADD, WN_rtype(rwn), rwn, ldid);
3726
          else
3727
            wn = WN_Binary(OPR_SUB, WN_rtype(rwn), rwn, ldid);
3728
           return wn;
3729
         }
3730
        // similar to above, but check for cond ? x|1 : x; which is just x|cond
3731
        else if (WN_operator(rwn) == OPR_LDID
3732
                   && WN_operator(lwn) == OPR_BIOR
3733
                   && WN_Simp_Compare_Trees ( WN_kid0(lwn), rwn ) == 0
3734
                   && WN_operator(WN_kid1(lwn)) == OPR_INTCONST
3735
                   && WN_const_val(WN_kid1(lwn)) == 1)
3736
        {
3737
          DevWarn("transform cselect back to straightline code");
3738
          ST *st = Gen_Temp_Symbol (MTYPE_To_TY(WN_rtype(test)), "_cond");
3739
          wn = WN_Stid (WN_rtype(test), 0, st, ST_type(st),
3740
                        test, 0);
3741
          WN_Set_Linenum ( wn, VHO_Srcpos );
3742
          WN_INSERT_BlockLast ( block, wn );
3743
 
3744
          WN *ldid = WN_Ldid (WN_rtype(test), 0, st, ST_type(st));
3745
          if (WN_rtype(test) != WN_rtype(rwn))
3746
            ldid = WN_Cvt(WN_rtype(test), WN_rtype(rwn), ldid);
3747
          wn = WN_Binary(OPR_BIOR, WN_rtype(rwn), rwn, ldid);
3748
          return wn;
3749
        }
3750
// could look for other patterns, but wait and see what shows up.
3751
 #endif
3752 2 marcel
      }
3753
    }
3754
  }
3755
 
3756
  if ( WN_first(cflow_block) )
3757
    WN_INSERT_BlockLast ( block, cflow_block );
3758
 
3759
  if ( opcode == OPC_VCSELECT )
3760
    vcselect = TRUE;
3761
 
3762
  else {
3763
 
3764 1411 laijx
    if ( opcode == OPC_MCSELECT ) {
3765 2 marcel
 
3766
      FmtAssert ( (    WN_opcode(lwn) == OPC_MLOAD
3767
                    && WN_opcode(rwn) == OPC_MLOAD ),
3768
                  ("unimplemented case encountered in OPC_MCSELECT") );
3769
 
3770
      mcselect   = TRUE;
3771
      preg_mtype = Pointer_Mtype;
3772
      lwn_offset = WN_offset(lwn);
3773
      rwn_offset = WN_offset(rwn);
3774
      swn        = WN_kid1(lwn);
3775
      ty_idx     = WN_ty(lwn);
3776
      lwn        = WN_kid0(lwn);
3777
      rwn        = WN_kid0(rwn);
3778
 
3779
      if ( lwn_offset == rwn_offset )
3780
        offset = lwn_offset;
3781
 
3782
      else {
3783
 
3784
        offset = 0;
3785
        addopc = OPCODE_make_op ( OPR_ADD, Pointer_Mtype, MTYPE_V );
3786
        intopc = OPCODE_make_op ( OPR_INTCONST, Pointer_Mtype, MTYPE_V );
3787
 
3788
        if ( lwn_offset )
3789
          lwn = WN_CreateExp2 ( addopc,
3790
                                lwn,
3791
                                WN_CreateIntconst ( intopc, lwn_offset ) );
3792
 
3793
        if ( rwn_offset )
3794
          rwn = WN_CreateExp2 ( addopc,
3795
                                rwn,
3796
                                WN_CreateIntconst ( intopc, rwn_offset ) );
3797
      }
3798
    }
3799
 
3800
    else {
3801
 
3802
      preg_mtype = WN_rtype(wn);
3803
    }
3804
 
3805
    vho_lower_set_st_addr_info ( lwn, ADDRESS_SAVED );
3806
    vho_lower_set_st_addr_info ( rwn, ADDRESS_SAVED );
3807
 
3808
    preg = Create_Preg (preg_mtype, vho_lower_cselect_name);
3809
 
3810
    preg_st     = MTYPE_To_PREG ( preg_mtype );
3811
    preg_ty_idx = Be_Type_Tbl(preg_mtype);
3812
    opcode      = OPCODE_make_op ( OPR_STID, MTYPE_V, preg_mtype );
3813
  }
3814
 
3815
  if (    cflow_bool_info.used_true_label
3816
       || cflow_bool_info.used_false_label ) {
3817
 
3818
    LABEL_Init (New_LABEL (CURRENT_SYMTAB, join_label),
3819
  0, LKIND_DEFAULT);
3820
 
3821
    if ( cflow_bool_info.used_true_label ) {
3822
 
3823
      wn = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info.true_label, 0, NULL );
3824
      WN_Set_Linenum ( wn, VHO_Srcpos );
3825
 
3826
      WN_INSERT_BlockLast ( block, wn );
3827
    }
3828
 
3829
    if ( WN_first(cflow_block1 ) )
3830
      WN_INSERT_BlockLast ( block, cflow_block1 );
3831
 
3832
    if ( ! vcselect ) {
3833
 
3834
      lwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, lwn );
3835
      WN_Set_Linenum ( lwn, VHO_Srcpos );
3836
 
3837
      WN_INSERT_BlockLast ( block, lwn );
3838
    }
3839
 
3840
    wn = WN_CreateGoto ( (ST_IDX) NULL, join_label );
3841
    WN_Set_Linenum ( wn, VHO_Srcpos );
3842
    if (Cur_PU_Feedback)
3843
      Cur_PU_Feedback->Annot( wn, FB_EDGE_OUTGOING, FB_FREQ_UNKNOWN );
3844
 
3845
    WN_INSERT_BlockLast ( block, wn );
3846
 
3847
    wn = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info.false_label, 0, NULL );
3848
    WN_Set_Linenum ( wn, VHO_Srcpos );
3849
 
3850
    WN_INSERT_BlockLast ( block, wn );
3851
 
3852
    if ( WN_first(cflow_block2 ) )
3853
      WN_INSERT_BlockLast ( block, cflow_block2 );
3854
 
3855
    if ( ! vcselect ) {
3856
 
3857
      rwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, rwn );
3858
      WN_Set_Linenum ( rwn, VHO_Srcpos );
3859
 
3860
      WN_INSERT_BlockLast ( block, rwn );
3861
    }
3862
 
3863
    wn = WN_CreateLabel ( (ST_IDX) 0, join_label, 0, NULL );
3864
    WN_Set_Linenum ( wn, VHO_Srcpos );
3865
 
3866
    WN_INSERT_BlockLast ( block, wn );
3867
  }
3868
 
3869
  else {
3870
 
3871
    if ( ! vcselect ) {
3872
 
3873
      // CSELECT                             IF
3874
      //  <test>                              <test>
3875
      //  <then_expr>                        THEN
3876
      //  <else_expr>            ===>          <then_expr>
3877
      //                                      STID <preg>
3878
      //                                     ELSE
3879
      //                                       <else_expr>
3880
      //                                      STID <preg>
3881
      //                                     END_IF
3882
 
3883
      lwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, lwn );
3884
      WN_Set_Linenum ( lwn, VHO_Srcpos );
3885
 
3886
      WN_INSERT_BlockLast ( cflow_block1, lwn );
3887
 
3888
      rwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, rwn );
3889
      WN_Set_Linenum ( rwn, VHO_Srcpos );
3890
 
3891
      WN_INSERT_BlockLast ( cflow_block2, rwn );
3892
    }
3893
 
3894
    wn = WN_CreateIf ( test, cflow_block1, cflow_block2 );
3895
    WN_Set_Linenum ( wn, VHO_Srcpos );
3896
    if ( Cur_PU_Feedback ) {
3897
      Cur_PU_Feedback->FB_lower_branch( wn_cselect, wn );
3898
    }
3899
 
3900
    WN_INSERT_BlockLast ( block, wn );
3901
  }
3902
 
3903
  if ( !vcselect ) {
3904
 
3905
    opcode = OPCODE_make_op ( OPR_LDID, Promoted_Mtype [preg_mtype],
3906
                              preg_mtype );
3907
    wn = WN_CreateLdid ( opcode, preg, preg_st, preg_ty_idx );
3908
 
3909
    if ( mcselect )
3910
      wn = WN_CreateMload ( offset, ty_idx, wn, swn );
3911
  }
3912
 
3913
  else
3914
    wn = NULL;
3915
 
3916
  return wn;
3917
} /* vho_lower_cselect */
3918
 
3919
 
3920
#if VHO_DEBUG
3921
#define record_combine_loads_failure(arg1,arg2) \
3922
  fprintf (stderr, "[%d] combine_load_failure at %d of vho_lower.c\n", \
3923
     arg1, arg2);
3924
#else
3925
#define record_combine_loads_failure(x,y)
3926
#endif /* VHO_DEBUG */
3927
 
3928
WN *
3929
vho_lower_combine_loads ( WN * wn )
3930
{
3931
  TYPE_ID    mtype;
3932
  OPCODE     opcode;
3933
  OPCODE     add_opc;
3934
  OPCODE     or_opc;
3935
  OPCODE     shift_opc;
3936
  OPCODE     load_opcode;
3937
  OPERATOR   wn_operator;
3938
  OPERATOR   load_operator;
3939
  INT32      bytes;
3940
  INT32      size;
3941
  INT32      item_size;
3942
  INT32      last_item_size;
3943
  INT32      shift_bits;
3944
  INT32      shift_bytes;
3945
  INT32      last_index;
3946
  WN       * source;
3947
  WN       * lwn;
3948
  WN       * swn;
3949
  WN       * twn;
3950
  WN       * awn1;
3951
  WN       * awn2;
3952
  BOOL       combine;
3953
 
3954
  opcode = WN_opcode(wn);
3955
 
3956
  if ( opcode == OPC_U4ADD || opcode == OPC_U4BIOR ) {
3957
    add_opc   = OPC_U4ADD;
3958
    or_opc    = OPC_U4BIOR;
3959
    shift_opc = OPC_U4SHL;
3960
    size      = 4;
3961
  }
3962 1950 laijx
  else if ( opcode == OPC_U8ADD || opcode == OPC_U8BIOR ) {
3963 2 marcel
    add_opc   = OPC_U8ADD;
3964
    or_opc    = OPC_U8BIOR;
3965
    shift_opc = OPC_U8SHL;
3966
    size      = 8;
3967
  }
3968
  else {
3969
    record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
3970
    return wn;
3971
  }
3972
 
3973
  bytes   = 0;
3974
  source  = NULL;
3975
  combine = TRUE;
3976
  lwn     = WN_kid0(wn);
3977
  swn     = WN_kid1(wn);
3978
 
3979
  if ( WN_opcode(swn) != shift_opc ) {
3980
    if ( WN_opcode(lwn) == shift_opc ) {
3981
      swn = lwn;
3982
      lwn = WN_kid1(wn);
3983
    }
3984
    else {
3985
      combine = FALSE;
3986
      record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
3987
    }
3988
  }
3989
 
3990
  mtype = WN_desc(lwn);
3991
 
3992
  if ( !MTYPE_is_unsigned(mtype) ) {
3993
    combine = FALSE;
3994
    record_combine_loads_failure ((INT32) VHO_Srcpos,  __LINE__);
3995
  }
3996
 
3997
  load_opcode   = WN_opcode(lwn);
3998
  load_operator = OPCODE_operator(load_opcode);
3999
 
4000
  if (    combine
4001
       && WN_operator(WN_kid1(swn)) == OPR_INTCONST
4002
       && ( load_operator == OPR_LDID || load_operator == OPR_ILOAD ) ) {
4003
    bytes  = TY_size(WN_ty(lwn));
4004
    source = lwn;
4005
    last_item_size = bytes;
4006
 
4007
    if (    load_operator == OPR_ILOAD
4008
         && WN_operator(WN_kid0(lwn)) == OPR_ARRAY )
4009
      last_index = WN_kid_count(WN_kid0(lwn)) - 1;
4010
 
4011
    while ( swn ) {
4012
      shift_bits = WN_const_val(WN_kid1(swn));
4013
      if ( shift_bits == 0 || shift_bits % 8 ) {
4014
        combine = FALSE;
4015
        record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4016
        break;
4017
      }
4018
 
4019
      shift_bytes = shift_bits >> 3;
4020
 
4021
      lwn         = WN_kid0(swn);
4022
      opcode      = WN_opcode(lwn);
4023
      wn_operator = OPCODE_operator(opcode);
4024
 
4025
      if ( wn_operator == OPR_LDID || wn_operator == OPR_ILOAD )
4026
        swn = NULL;
4027 1950 laijx
      else if ( opcode == add_opc || opcode == or_opc ) {
4028 2 marcel
        swn = WN_kid1(lwn);
4029
        lwn = WN_kid0(lwn);
4030
        if ( WN_opcode(swn) != shift_opc ) {
4031
          if ( WN_opcode(lwn) == shift_opc ) {
4032
            twn = lwn;
4033
            lwn = swn;
4034
            swn = twn;
4035
          }
4036
          else {
4037
            combine = FALSE;
4038
            record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4039
            break;
4040
          }
4041
        }
4042
 
4043
        if ( WN_operator(WN_kid1(swn)) != OPR_INTCONST ) {
4044
          combine = FALSE;
4045
          record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4046
          break;
4047
        }
4048
 
4049
        wn_operator = WN_operator(lwn);
4050
 
4051
        if ( wn_operator != OPR_LDID && wn_operator != OPR_ILOAD ) {
4052
          combine = FALSE;
4053
          record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4054
          break;
4055
        }
4056
      }
4057
      else {
4058
        combine = FALSE;
4059
        record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4060
        break;
4061
      }
4062
 
4063
      item_size = TY_size(WN_ty(lwn));
4064
 
4065
      if ( item_size != shift_bytes ) {
4066
        combine = FALSE;
4067
        record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4068
        break;
4069
      }
4070
 
4071
      bytes += item_size;
4072
 
4073
      if ( bytes > size ) {
4074
        combine = FALSE;
4075
        record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4076
        break;
4077
      }
4078
 
4079
      opcode      = WN_opcode(lwn);
4080
      wn_operator = OPCODE_operator(opcode);
4081
 
4082
      if ( wn_operator != load_operator ) {
4083
        combine = FALSE;
4084
        record_combine_loads_failure ((INT32) VHO_Srcpos,  __LINE__);
4085
        break;
4086
      }
4087
 
4088
      mtype = OPCODE_desc(opcode);
4089
 
4090
      if ( !MTYPE_is_unsigned(mtype) ) {
4091
        combine = FALSE;
4092
        record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4093
        break;
4094
      }
4095
 
4096
      if ( load_operator == OPR_LDID ) {
4097
        if (    WN_st(source) != WN_st(lwn)
4098
             && WN_offset(source) != WN_offset(lwn) + last_item_size ) {
4099
          combine = FALSE;
4100
          record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4101
          break;
4102
        }
4103
      }
4104 1950 laijx
      else if ( load_operator == OPR_ILOAD ) {
4105 2 marcel
        awn1 = WN_kid0(source);
4106
        awn2 = WN_kid0(lwn);
4107
        if ( WN_load_offset(source) == WN_load_offset(lwn) + last_item_size ) {
4108
          if ( WN_Simp_Compare_Trees ( awn1, awn2 ) ) {
4109
            combine = FALSE;
4110
            record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4111
            break;
4112
          }
4113
        }
4114 1950 laijx
  else if ( WN_load_offset(source) == WN_load_offset(lwn) ) {
4115 2 marcel
          if (    WN_operator(awn1) == OPR_ARRAY
4116
               && WN_operator(WN_kid(awn1,last_index)) == OPR_INTCONST ) {
4117
            WN_const_val(WN_kid(awn1,last_index)) -= 1;
4118
 
4119
            if ( WN_Simp_Compare_Trees ( awn1, awn2 ) ) {
4120
              WN_const_val(WN_kid(awn1,last_index)) += 1;
4121
              combine = FALSE;
4122
              record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4123
              break;
4124
            }
4125
            else
4126
              WN_const_val(WN_kid(awn1,last_index)) += 1;
4127
          }
4128
          else {
4129
            combine = FALSE;
4130
            record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4131
            break;
4132
          }
4133
        }
4134
        else {
4135
          combine = FALSE;
4136
          record_combine_loads_failure ((INT32) VHO_Srcpos,  __LINE__);
4137
          break;
4138
        }
4139
      }
4140
      else {
4141
        combine = FALSE;
4142
        record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
4143
        break;
4144
      }
4145
 
4146
      source = lwn;
4147
      last_item_size = item_size;
4148
    }
4149
  }
4150
 
4151
  if ( combine && bytes == size ) {
4152
    TY_IDX aty_idx;
4153
    TY_IDX uty_idx;
4154
    TY_IDX pty_idx;
4155
 
4156
    if ( size == 4 ) {
4157
      aty_idx = Be_Type_Tbl(MTYPE_U4);
4158
      uty_idx = vho_u4a1_ty_idx;
4159
 
4160
      if ( uty_idx == (TY_IDX) 0 ) {
4161
        uty_idx = aty_idx;
4162
        Set_TY_align (uty_idx, 1);
4163
        pty_idx = Make_Pointer_Type ( uty_idx, TRUE );
4164
 
4165
        vho_u4a1_ty_idx = uty_idx;
4166
      }
4167
      else
4168
        pty_idx = TY_pointer(uty_idx);
4169
    }
4170
    else {
4171
      aty_idx = Be_Type_Tbl(MTYPE_U8);
4172
      uty_idx = vho_u8a1_ty_idx;
4173
 
4174
      if ( uty_idx == (TY_IDX) 0 ) {
4175
        uty_idx = aty_idx;
4176
        Set_TY_align (uty_idx, 1);
4177
        pty_idx = Make_Pointer_Type ( uty_idx, TRUE );
4178
 
4179
        vho_u8a1_ty_idx = uty_idx;
4180
      }
4181
      else
4182
        pty_idx = TY_pointer(uty_idx);
4183
    }
4184
 
4185
    if ( load_operator == OPR_LDID ) {
4186
      lwn = WN_COPY_Tree(lwn);
4187
      WN_DELETE_Tree(wn);
4188
      wn = lwn;
4189
      opcode = size == 4 ? OPC_U4U4LDID : OPC_U8U8LDID;
4190
      WN_set_opcode(wn,opcode);
4191
      WN_set_ty(wn,uty_idx);
4192
    }
4193
    else {
4194
      lwn = WN_COPY_Tree(lwn);
4195
      WN_DELETE_Tree(wn);
4196
      wn = lwn;
4197
      opcode = size == 4 ? OPC_U4U4ILOAD : OPC_U8U8ILOAD;
4198
      WN_set_opcode(wn,opcode);
4199
      WN_set_ty(wn,aty_idx);
4200
      WN_set_load_addr_ty(wn,pty_idx);
4201
    }
4202
  }
4203
 
4204
  return wn;
4205
} /* vho_lower_combine_loads */
4206
 
4207 135 marcel
#ifdef KEY
4208
// Utility function to traverse through an aggregate type and determine
4209
// if any field/element is floating-point: bug 7770
4210
// Called by vho_lower_mparm(), if there is any FP field, the mparm cannot
4211
// be transformed.
4212
// Return 1 if OK to transform, 0 if cannot be transformed.
4213
static inline BOOL
4214
traverse_struct (const TY_IDX ty)
4215
{
4216
  Is_True (TY_size(ty) <= 8, ("Type size cannot exceed 8"));
4217
  if (TY_kind (ty) == KIND_STRUCT)
4218
  {
4219
    FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty));
4220
    do
4221
    {
4222
      FLD_HANDLE fld(fld_iter);
4223
      if (TY_size(FLD_type(fld)) == 0)
4224
        continue;
4225
      if (!traverse_struct (FLD_type(fld))) return 0;
4226
    } while (!FLD_last_field(fld_iter++));
4227
  }
4228
  else if (TY_kind (ty) == KIND_ARRAY)
4229
    return traverse_struct (TY_etype (ty));
4230
  else
4231
    switch (TY_mtype (ty))
4232
    {
4233
      case MTYPE_F4:
4234
      case MTYPE_F8:
4235
      case MTYPE_C4: return 0;
4236
      default: return 1;
4237
    }
4238 2 marcel
 
4239 135 marcel
  return 1;
4240
}
4241
 
4242
// If the struct under MPARM is of size 4 or 8, change LDID from M
4243
// type to the appropriate type (U4/U8).
4244
static inline WN *
4245
vho_lower_mparm (WN * wn)
4246
{
4247
  WN * kid = WN_kid0 (wn);
4248
  if (WN_opcode (kid) != OPC_MMLDID) return wn;
4249
 
4250
  TY_IDX ty = WN_ty (kid);
4251
  INT64 bytes = TY_size (ty);
4252
 
4253 1950 laijx
  if (VHO_Struct_Opt &&
4254 135 marcel
      (bytes == 4 || bytes == 8) &&
4255
      TY_size (WN_ty (wn)) == bytes &&
4256 1411 laijx
      ST_class (WN_st (kid)) != CLASS_PREG
4257
#ifdef TARG_X8664
4258
      && (Is_Target_32bit() ||
4259
          traverse_struct (WN_ty (wn)))
4260 1950 laijx
#elif defined(TARG_MIPS) || defined(TARG_IA64)  // bug 12809
4261 1411 laijx
      && traverse_struct (WN_ty(wn))
4262
#endif
4263 1950 laijx
#if defined(TARG_SL)
4264
      && (bytes == 4)
4265
#endif
4266 1411 laijx
      )
4267 135 marcel
  {
4268
    TYPE_ID mtype = (bytes == 4) ? MTYPE_U4 : MTYPE_U8;
4269
    WN_set_rtype (wn, mtype);
4270
    WN_set_rtype (kid, mtype);
4271
    WN_set_desc (kid, mtype);
4272 749 hucheng
 
4273
    // bugs 9989, 10139
4274 1950 laijx
    // bug fix for OSP_258
4275 749 hucheng
    INT field_id;
4276 1950 laijx
    Is_True (WN_field_id(kid) == 0,("vho_lower_mparm: Expected field-id zero"));
4277 749 hucheng
    if ((TY_kind(ty) == KIND_STRUCT) &&
4278
        (field_id /* assign */ = single_field_in_struct (ty)))
4279
      WN_set_field_id (kid, field_id);
4280 135 marcel
  }
4281
 
4282
  return wn;
4283
}
4284
#endif
4285
 
4286 2 marcel
/* ============================================================================
4287
 *
4288
 * WN *vho_lower_expr ( WN * wn, WN * block, BOOL_INFO * bool_info )
4289
 *
4290
 * Given a tree, this routine traverses the tree performing lowering
4291
 * actions for
4292
 *
4293
 *   SWITCH into a sequence of if-else, compgoto and/or binary search
4294
 *   MSTORE into STID/ISTORE over LDID/ILOAD if the structure is
4295
 *     sufficiently small.
4296
 *
4297
 * ============================================================================
4298
 */
4299
 
4300
static WN *
4301 1950 laijx
vho_lower_expr ( WN * wn, WN * block, BOOL_INFO * bool_info, BOOL is_return )
4302 2 marcel
{
4303
  OPCODE     opcode;
4304
  OPERATOR   wn_operator;
4305
  mINT16     nkids;
4306
  mINT16     i;
4307
 
4308
  opcode      = WN_opcode(wn);
4309
  wn_operator = OPCODE_operator(opcode);
4310
  nkids       = WN_kid_count(wn);
4311
 
4312
  switch ( wn_operator ) {
4313
 
4314
    case OPR_ILOAD:
4315
 
4316
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4317
 
4318
      if (    VHO_Iload_Opt
4319
           && WN_operator(WN_kid0(wn)) == OPR_LDA ) {
4320
 
4321
        INT64 offset;
4322
 
4323
        offset = WN_load_offset(wn) + WN_lda_offset(WN_kid0(wn));
4324
 
4325
        if ( offset >= INT32_MIN && offset <= INT32_MAX ) {
4326
 
4327
          WN * wn1;
4328
 
4329
          wn1 = WN_CreateLdid ( OPCODE_make_op ( OPR_LDID,
4330
                                                 OPCODE_rtype(opcode),
4331
                                                 OPCODE_desc(opcode) ),
4332
                                offset,
4333
                                WN_st_idx(WN_kid0(wn)),
4334 71 marcel
                                WN_ty(wn),
4335
                                WN_field_id(wn) );
4336 2 marcel
/*
4337
          fprintf ( stderr, "ILOAD->LDID old\n" );
4338
          fdump_tree ( stderr, wn );
4339
          fprintf ( stderr, "ILOAD->LDID new\n" );
4340
          fdump_tree ( stderr, wn1 );
4341
*/
4342
          wn = wn1;
4343
        }
4344
      }
4345
 
4346
      break;
4347
 
4348
    case OPR_ILOADX:
4349
 
4350
      FmtAssert ( TRUE, ("unexpected operator encountered in vho_lower") );
4351
      break;
4352
 
4353
    case OPR_MLOAD:
4354
 
4355
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4356
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4357
      break;
4358
 
4359
    case OPR_ARRAY:
4360
 
4361
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4362
 
4363
      for ( i = (nkids + 1) >> 1; i < nkids; i++ )
4364
        WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
4365
      break;
4366
 
4367
    case OPR_INTRINSIC_OP:
4368
 
4369 83 marcel
#ifndef TARG_X8664
4370 2 marcel
      for ( i = 0; i < nkids; i++ )
4371
        WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
4372
      break;
4373 83 marcel
#else
4374
      {
4375
  // Fortran expression like a[i]**n can be vectorized if we expand
4376
  // inline before LNO. However, we do this only for small values of n.
4377
  // The math library (powd) may do a better job for large values of n.
4378
  if ( WN_intrinsic(wn) == INTRN_F8I4EXPEXPR ||
4379
       WN_intrinsic(wn) == INTRN_F4I4EXPEXPR ) {
4380
    WN* parm1 = WN_kid1(wn);
4381
    WN* exp = WN_kid0(parm1);
4382
    if (WN_operator(exp) == OPR_INTCONST &&
4383
        WN_const_val(exp) > 0 &&
4384
        WN_const_val(exp) <= 5) {
4385
      INT n = WN_const_val(exp);
4386 749 hucheng
      WN_kid0(WN_kid0(wn)) = vho_lower_expr(WN_kid0(WN_kid0(wn)),
4387
              block, NULL); //bug 8576
4388 83 marcel
      WN* opnd = WN_COPY_Tree ( WN_kid0(WN_kid0(wn)) );
4389
      if ( n == 1 ) {
4390
        wn = opnd; break;
4391
      }
4392
      wn = WN_Mpy(WN_rtype(wn), opnd, WN_COPY_Tree ( opnd )); n-= 2;
4393
      for (;n > 0; n--)
4394
        wn = WN_Mpy(WN_rtype(wn), wn, WN_COPY_Tree ( opnd ));
4395
      break;
4396
    }
4397
  }
4398 2 marcel
 
4399 83 marcel
  for ( i = 0; i < nkids; i++ )
4400
    WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
4401
  break;
4402
      }
4403
#endif
4404
 
4405 2 marcel
    case OPR_TAS:
4406
 
4407
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4408
      break;
4409
 
4410
    case OPR_SELECT:
4411
 
4412
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4413
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4414
      WN_kid2(wn) = vho_lower_expr (WN_kid2(wn), block, NULL);
4415
      break;
4416
 
4417
    case OPR_CSELECT:
4418
 
4419
      wn = vho_lower_cselect ( wn, block, bool_info);
4420
      break;
4421
 
4422
    case OPR_CVT:
4423
    case OPR_CVTL:
4424
 
4425
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4426
      break;
4427
 
4428
    case OPR_NEG:
4429
    case OPR_ABS:
4430
    case OPR_SQRT:
4431
    case OPR_REALPART:
4432
    case OPR_IMAGPART:
4433
    case OPR_PAREN:
4434
    case OPR_RND:
4435
    case OPR_TRUNC:
4436
    case OPR_CEIL:
4437
    case OPR_FLOOR:
4438
    case OPR_BNOT:
4439
    case OPR_LNOT:
4440
    case OPR_ALLOCA:
4441 581 tianwei
    case OPR_EXTRACT_BITS:  // bug fix for OSP_184
4442 2 marcel
 
4443
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4444
      break;
4445
 
4446
    case OPR_ASM_INPUT:
4447
 
4448
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4449
      break;
4450
 
4451
    case OPR_ADD:
4452
    case OPR_SUB:
4453
    case OPR_MPY:
4454
    case OPR_DIV:
4455
    case OPR_MOD:
4456
    case OPR_REM:
4457
    case OPR_DIVREM:
4458 71 marcel
#ifdef KEY
4459
    case OPR_COMPOSE_BITS:
4460
#endif
4461 2 marcel
 
4462
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4463
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4464
 
4465
      if ( VHO_Combine_Loads && wn_operator == OPR_ADD )
4466
        wn = vho_lower_combine_loads ( wn );
4467
      break;
4468
 
4469
    case OPR_LOWPART:
4470
    case OPR_HIGHPART:
4471
 
4472
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4473
      break;
4474
 
4475
    case OPR_MAX:
4476
    case OPR_MIN:
4477
    case OPR_MINMAX:
4478
 
4479
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4480
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4481
      break;
4482
 
4483
    case OPR_MINPART:
4484
    case OPR_MAXPART:
4485
 
4486
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4487
      break;
4488
 
4489
    case OPR_BAND:
4490
    case OPR_BIOR:
4491
    case OPR_BNOR:
4492
    case OPR_BXOR:
4493
    case OPR_LAND:
4494
    case OPR_LIOR:
4495
 
4496
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4497
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4498
 
4499
      if ( VHO_Combine_Loads && wn_operator == OPR_BIOR )
4500
        wn = vho_lower_combine_loads ( wn );
4501
      break;
4502
 
4503
    case OPR_CAND:
4504
    case OPR_CIOR:
4505
 
4506
      wn = vho_lower_cand_cior ( wn, block, bool_info );
4507
      break;
4508
 
4509
    case OPR_SHL:
4510
    case OPR_ASHR:
4511
    case OPR_LSHR:
4512
    case OPR_COMPLEX:
4513
 
4514
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4515
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4516
      break;
4517
 
4518
    case OPR_RECIP:
4519
    case OPR_RSQRT:
4520
 
4521
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4522
      break;
4523
 
4524
    case OPR_MADD:
4525
    case OPR_MSUB:
4526
    case OPR_NMADD:
4527
    case OPR_NMSUB:
4528
 
4529
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4530
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4531
      WN_kid2(wn) = vho_lower_expr (WN_kid2(wn), block, NULL);
4532
      break;
4533
 
4534
    case OPR_IO_ITEM:
4535
 
4536
      for ( i = 0; i < nkids; i++ )
4537
        WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
4538
      break;
4539
 
4540
    case OPR_EQ:
4541
    case OPR_NE:
4542
    case OPR_GT:
4543
    case OPR_GE:
4544
    case OPR_LT:
4545
    case OPR_LE:
4546
 
4547
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4548
      WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4549
      break;
4550
 
4551
    case OPR_LDID:
4552 1950 laijx
#ifdef TARG_NVISA
4553
      // check for a load past the end of the struct
4554
      if (ST_class(WN_st(wn)) == CLASS_VAR) {
4555
        TY_IDX ty = ST_type(WN_st(wn));
4556
        if (TY_kind(ty) == KIND_STRUCT && WN_offset(wn) >= TY_size(ty))
4557
        {
4558
          ErrMsgSrcpos(EC_Load_Past_Struct, VHO_Srcpos);
4559
        }
4560
      }
4561
#endif
4562 2 marcel
      break;
4563
 
4564
    case OPR_LDA:
4565
    case OPR_CONST:
4566
    case OPR_INTCONST:
4567
    case OPR_IDNAME:
4568
 
4569
      /* No need to lower */
4570
      break;
4571
 
4572
    case OPR_LOOP_INFO:
4573
 
4574
      FmtAssert ( TRUE, ("unexpected operator encountered in vho_lower") );
4575
      break;
4576
 
4577
    case OPR_PARM:
4578
 
4579 135 marcel
#ifdef KEY // bug 7741
4580
      wn = vho_lower_mparm (wn);
4581
#endif
4582 2 marcel
      WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4583
      break;
4584
 
4585
    case OPR_TRIPLET:
4586
    case OPR_ARRAYEXP:
4587
    case OPR_ARRSECTION:
4588
    case OPR_WHERE:
4589
    case OPR_OPT_RESERVE2:
4590
 
4591
      FmtAssert ( TRUE, ("unexpected operator encountered in vho_lower") );
4592
      break;
4593
 
4594
    case OPR_COMMA:
4595
 
4596 1950 laijx
      wn = vho_lower_comma ( wn, block, bool_info, is_return );
4597 2 marcel
/*
4598
      comma_block = vho_lower_block (WN_kid0(wn));
4599
      WN_INSERT_BlockLast ( block, comma_block );
4600
      wn = vho_lower_expr (WN_kid1(wn), block, bool_info);
4601
*/
4602
      break;
4603
 
4604
    case OPR_RCOMMA:
4605
 
4606
      wn = vho_lower_rcomma ( wn, block, bool_info );
4607
      break;
4608
 
4609
    case OPR_HIGHMPY:
4610
    case OPR_XMPY:
4611
 
4612
      break;
4613
 
4614
    case OPR_RROTATE:
4615
    {
4616 749 hucheng
#ifdef TARG_X8664
4617
      // By default, generate rotate instruction only if it is C++ (bug 7932)
4618
      // Can be crontrolled by internal flag -VHO:rotate
4619 861 hucheng
      if (!VHO_Generate_Rrotate_Set && PU_cxx_lang (Get_Current_PU()) &&
4620 1950 laijx
          (Is_Target_64bit() || MTYPE_byte_size(WN_desc(wn)) <= 4))
4621 749 hucheng
        VHO_Generate_Rrotate = TRUE;
4622
 
4623
      if (!VHO_Generate_Rrotate)
4624
#endif
4625
      {
4626
        TYPE_ID  desc  = WN_desc(wn);
4627
        TYPE_ID  rtype = WN_rtype(wn);
4628
        INT32    size  = 8 * TY_size (Be_Type_Tbl (desc));
4629
        WN      *wn0   = vho_lower_expr (WN_kid0(wn), block, NULL);
4630
        WN      *wn1   = vho_lower_expr (WN_kid1(wn), block, NULL);
4631
        TYPE_ID  shift_rtype = WN_rtype(wn1);
4632
        WN      *rshift = WN_Lshr (rtype, WN_COPY_Tree (wn0), WN_COPY_Tree (wn1));
4633
        WN      *lshift = WN_Shl  (rtype, wn0,
4634
                                   WN_Binary (OPR_SUB, shift_rtype,
4635
                                              WN_Intconst (shift_rtype, size),
4636
                                              wn1));
4637 135 marcel
#ifdef TARG_X8664 // bug 4552
4638 1950 laijx
        // This is now unused code, but keep the fix for the record.
4639
        if (size < MTYPE_size_min(rtype))
4640
    lshift = WN_CreateCvtl(OPR_CVTL, Mtype_TransferSign(MTYPE_U4, rtype),
4641
          MTYPE_V, size, lshift);
4642 135 marcel
#endif
4643 749 hucheng
        wn  = WN_Bior (rtype, lshift, rshift);
4644
      }
4645
#ifdef TARG_X8664
4646
      else
4647
      {
4648
        WN_kid0 (wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
4649
        WN_kid1 (wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
4650
      }
4651
#endif // TARG_X8664
4652 2 marcel
      break;
4653
    }
4654
 
4655
    default:
4656
 
4657
      FmtAssert ( TRUE, ("unknown operator encountered in vho_lower_expr") );
4658
      break;
4659
  }
4660
 
4661
  return wn;
4662
} /* vho_lower_expr */
4663
 
4664
 
4665
static WN *
4666
vho_lower_compgoto ( WN * wn, WN * block )
4667
{
4668
  WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
4669
  WN_kid1(wn) = vho_lower_block ( WN_kid1(wn) );
4670
  return wn;
4671
} /* vho_lower_compgoto */
4672
 
4673
 
4674
static WN *
4675
vho_lower_switch ( WN * wn, WN * block )
4676
{
4677
  WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
4678
  wn = VHO_Lower_Switch ( wn );
4679
  return wn;
4680
} /* vho_lower_switch */
4681
 
4682
 
4683
static WN *
4684
vho_lower_casegoto ( WN * wn, WN * block )
4685
{
4686
  return wn;
4687
} /* vho_lower_casegoto */
4688
 
4689
 
4690
static WN *
4691
vho_lower_truebr ( WN * wn, WN * block )
4692
{
4693
  WN        * test;
4694
  WN        * test_block;
4695
  BOOL_INFO   bool_info;
4696
 
4697
  test_block = WN_CreateBlock ();
4698
  WN_Set_Linenum ( test_block, VHO_Srcpos );
4699
 
4700
  vho_initialize_bool_info (&bool_info);
4701
  bool_info.true_label  = WN_label_number(wn);
4702
 
4703
  LABEL_Init (New_LABEL (CURRENT_SYMTAB, bool_info.false_label),
4704
  0, LKIND_DEFAULT);
4705
 
4706
  test = vho_lower_expr ( WN_kid0(wn), test_block, &bool_info );
4707
 
4708
  if ( WN_first(test_block) ) {
4709
    WN_INSERT_BlockLast ( block, test_block );
4710
  }
4711
 
4712
  if ( test ) {
4713
    WN_kid0(wn) = test;
4714
  }
4715
 
4716
  else {
4717
    // TRUEBR <test> <true_label>    ===>    <test>
4718
    //                                       GOTO <true_label>
4719
    //                                       LABEL <false_label>
4720
 
4721
    WN *wn_goto = WN_CreateGoto ( (ST_IDX) NULL, bool_info.true_label );
4722
    WN_Set_Linenum ( wn_goto, VHO_Srcpos );
4723
    WN_INSERT_BlockLast ( block, wn_goto );
4724
 
4725
    WN *wn_label
4726
      = WN_CreateLabel ( (ST_IDX) 0, bool_info.false_label, 0, NULL );
4727
    WN_Set_Linenum ( wn_label, VHO_Srcpos );
4728
    WN_INSERT_BlockLast ( block, wn_label );
4729
 
4730
    // Don't update feedback; let propagation handle
4731
 
4732
    wn = NULL;
4733
  }
4734
 
4735
  return wn;
4736
} /* vho_lower_truebr */
4737
 
4738
 
4739
static WN *
4740
vho_lower_return ( WN * wn, WN * block )
4741
{
4742
  return wn;
4743
} /* vho_lower_return */
4744
 
4745
static BOOL
4746
vho_singleton_field (TY_IDX ty_idx)
4747
{
4748
  return FALSE;
4749
} /* vho_singleton_field */
4750
 
4751
static WN *
4752
vho_lower_return_val (WN* wn, WN* block)
4753
{
4754 1950 laijx
  WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL, WN_rtype(wn)==MTYPE_M );
4755 2 marcel
  return wn;
4756
} /* vho_lower_return_val */
4757
 
4758
static WN *
4759
vho_lower_istore ( WN * wn, WN * block )
4760
{
4761
  WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
4762
  WN_kid1(wn) = vho_lower_expr ( WN_kid1(wn), block, NULL );
4763
  return wn;
4764
} /* vho_lower_istore */
4765
 
4766
 
4767
static WN *
4768
vho_lower_mstore ( WN * wn, WN * block )
4769
{
4770
  WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
4771
  WN_kid1(wn) = vho_lower_expr ( WN_kid1(wn), block, NULL );
4772
  WN_kid(wn,2) = vho_lower_expr ( WN_kid(wn,2), block, NULL );
4773
  wn = VHO_Lower_Mstore ( wn );
4774
 
4775
  return wn;
4776
} /* vho_lower_mstore */
4777
 
4778
 
4779
static WN *
4780
vho_lower_stid ( WN * wn, WN * block )
4781
{
4782
  WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
4783 71 marcel
  if (WN_desc(wn) == MTYPE_M) {
4784
    /* lower MSTID */
4785
    wn = VHO_Lower_Mstid (wn);
4786
  }
4787
 
4788 2 marcel
  return wn;
4789
} /* vho_lower_stid */
4790
 
4791
 
4792
static WN *
4793
vho_lower_call ( WN * wn, WN * block )
4794
{
4795
  INT32 i;
4796 1950 laijx
#ifdef TARG_NVISA
4797
  if ((!ST_is_export_local(WN_st(wn)) || ST_sclass(WN_st(wn)) == SCLASS_EXTERN)
4798
        && !CLIST_enabled) // okay if producing C
4799
  {
4800
    // We only support calls to locally defined functions