Effect.xcc

Benoit Dupont de Dinechin (Benoit.Dupont-de-Dinechin@st.com).

Copyright 2002 - 2007 STMicroelectronics. Copyright 1995 - 1998 Commissariat a l'Energie Atomique.

This program is free software; you can redistribute it and/or modify it under the terms of either (at your option): the GNU General Public License (GPL) version 2; the GNU Lesser General Public License (LGPL) version 2.1; any later version of these licences as published by the Free Software Foundation.

EffectFlag— Enumerates the Effect flags.
Side Effect(s)
not in the Operation arguments or results.
Indirect Effect(s)
special cases for latency computations.
typedef enum {
  EffectFlag_Read = 0x0,        // Effect is a read to the target resource.
  EffectFlag_Write = 0x1,       // Effect is a write to the target resource.
  EffectFlag_Kill = 0x2,        // Effect is a write that kills the previous value.
  EffectFlag_Clobber = 0x4,     // Effect is a clobber: creates an undefined value.
  EffectFlag_Indirect = 0x8,    // Effect is indirect: from Label or Control.
  EffectFlag_Carried = 0x10,    // Effect is loop-carried read or partial def.
  EffectFlag_Supplied = 0x20,   // Effect is in the supplied dependence set.
  EffectFlag_InTrace = 0x40,    // Effect is indirect in the same BlockTrace.
} enum_EffectFlag;
typedef uint8_t EffectFlags;
Effect— Action of an Operation on a processor resource.

An effect materializes a read or a write on a state-holding processor resource (register, control, memory, etc.) represented as a Temporary.

An Effect is a side effect when its XXXINDEX is negative. Else the XXXINDEX is either the ARGINDEX or the RESINDEX, depending on the position in Operation.

struct Effect_ {
  //@args       Operation operation, Temporary temporary, EffectFlags flags, int index
  //@access NEXT        (Effect)(IDListItem_NEXT(this))
  Operation OPERATION;          // The Operation that creates this Effect.
  Temporary TEMPORARY;          // The Temporary this Effect applies to.
  int16_t XXXINDEX;             // Index in the Operation_xxxEFFECTS.
  //@access isSide      (Effect_XXXINDEX(this) < 0)
  EffectFlags FLAGS;    // This Effect flags.
  //@access isRead      ((Effect_FLAGS(this) & EffectFlag_Write) == 0)
  //@access isWrite     ((Effect_FLAGS(this) & EffectFlag_Write) != 0)
  //@access isKill      ((Effect_FLAGS(this) & EffectFlag_Kill) != 0)
  //@access isClobber   ((Effect_FLAGS(this) & EffectFlag_Clobber) != 0)
  //@access isIndirect  ((Effect_FLAGS(this) & EffectFlag_Indirect) != 0)
  //@access isCarried   ((Effect_FLAGS(this) & EffectFlag_Carried) != 0)
  //@access isSupplied  ((Effect_FLAGS(this) & EffectFlag_Supplied) != 0)
  //@access isInTrace   ((Effect_FLAGS(this) & EffectFlag_InTrace) != 0)
  int8_t RELAXABLE;             // The amount of inductive relaxation applicable.
  struct Lifetime_ *LIFETIME;   // The Lifetime this Effect belongs to.
  struct Effect_ *PRED;         // Dependence predecessor of this Effect.
  struct Effect_ *SUCC;         // Dependence successor of this Effect.
};
Effect_pretty— Pretty-print this Effet.
bool
Effect_pretty(Effect this, FILE *file);
Effect_operation— This Effect Operation.
static inline Operation
Effect_operation(Effect this)
{
  return Effect_OPERATION(this);
}
Effect_temporary— This Effect Temporary.
static inline Temporary
Effect_temporary(Effect this)
{
  return Effect_TEMPORARY(this);
}
Effect_setFlags— Set this Effect flags.
static inline void
Effect_setFlags(Effect this, unsigned flags)
{
  *Effect__FLAGS(this) |= flags;
}
Effect_clearFlags— Reset this Effect flags.
static inline void
Effect_clearFlags(Effect this, unsigned flags)
{
  *Effect__FLAGS(this) &= ~flags;
}
Effect_getRegisterRAWLatency— Get the Register RAW latency between two effects.
int
Effect_getRegisterRAWLatency(Effect this, Effect that, Processor processor, int extra);
Effect_getRegisterExtraWARLatency— The Register extra WAR latency between two effects.

Add an extra cycle to the WAR latency for operations that are positioned late in an issue group like control-flow operations. This prevents the scheduler to produce semantic invalid issue groups like:

[0]  CMP $b1 = ...
[0]  BR $b1, target

Here, Operation BR actually gets the old $b1 but it appears to get the new $b1.

static inline int
Effect_getRegisterExtraWARLatency(Effect this)
{
  Operation this_operation = Effect_OPERATION(this);
  Operator this_operator = Operation_operator(this_operation);
  return Operator_isControl(this_operator);
}
Effect_getRegisterWARLatency— Get the Register WAR latency between two effects.
int
Effect_getRegisterWARLatency(Effect this, Effect that, Processor processor);
Effect_getRegisterWAWLatency— Get the Register WAW latency between two effects.
int
Effect_getRegisterWAWLatency(Effect this, Effect that, Processor processor);
Effect_getRegionFlowLatency— Get the Control FLow latency between two effects.
static inline int
Effect_getRegionFlowLatency(Effect this, Effect that, Processor processor)
{
  // Control operations are positioned last in an issue group, so latency must be > 0.
  return 1;
}
Effect_getControlAntiLatency— Get the Control Anti latency between two effects.
static inline int
Effect_getControlAntiLatency(Effect this, Effect that, Processor processor)
{
  // TODO
  return 0;
}
Effect_getControlOutputLatency— Get the Control Output latency between two effects.
static inline int
Effect_getControlOutputLatency(Effect this, Effect that, Processor processor)
{
  Operation this_operation = Effect_OPERATION(this);
  Operation that_operation = Effect_OPERATION(that);
  if (Operator_isFall(Operation_operator(this_operation))) return 0;
  if (Operator_isFall(Operation_operator(that_operation))) return 0;
  // TODO
  return 1;
}
Effect_getMemoryFlowLatency— Get the Memory FLow latency between two effects.
int
Effect_getMemoryFlowLatency(Effect this, Effect that, Processor processor);
Effect_getMemoryAntiLatency— Get the Memory Anti latency between two effects.
int
Effect_getMemoryAntiLatency(Effect this, Effect that, Processor processor);
Effect_getMemoryOutputLatency— Get the Memory Output latency between two effects.
int
Effect_getMemoryOutputLatency(Effect this, Effect that, Processor processor);
EffectSeq— Sequence of effects on a particular Temporary.
struct EffectSeq_ {
  //@args Memory memory, int32_t estimate
  IStack_ ISTACK_;              // Stack of Effect(s).
  //@access ISTACK      EffectSeq__ISTACK_(this)
  //@access COUNT       (IStack_usedSize(EffectSeq_ISTACK(this))/sizeof(Effect))
  //@access MEMORY      IStack_memory(EffectSeq_ISTACK(this))
};
EffectSeq_istack— For use by EffectSeq_FOREACH_Effect.
static inline IStack
EffectSeq_istack(EffectSeq this)
{
  return EffectSeq_ISTACK(this);
}
EffectSeq_FOREACH_Effect— Iterate over this EffectSeq Effect(s).
#define EffectSeq_FOREACH_Effect(this, effect) { \
  IStack EffectSeq_ISTACK = EffectSeq_istack(this); \
  IStack_FOREACH(EffectSeq_ISTACK, Effect, EffectSeq__EFFECT) { \
    Effect effect = *EffectSeq__EFFECT;
#define EffectSeq_ENDEACH_Effect \
  } IStack_ENDEACH; \
}
EffectTable— Tabulate the Effect(s) by Operation.

The purpose of an EffectTable is to tabulate the Effect(s) of a sequence of Operation(s), for use in local optimizations. When an Operation is entered into an EffectTable, its side Effect(s) are computed if requested.

struct EffectTable_ {
  //@args       Memory memory, Procedure procedure, int32_t estimate
  IStack_ OPERATIONS_;          // This EffectTable Operation(s).
  //@access OPERATIONS  EffectTable__OPERATIONS_(this)
  //@access MEMORY      IStack_memory(EffectTable_OPERATIONS(this))
  //@access COUNT       (IStack_usedSize(EffectTable_OPERATIONS(this))/sizeof(Operation))
  HTable_ EFFECTSEQS_;          // Hash from Temporary to EffectSeq.
  //@access EFFECTSEQS  EffectTable__EFFECTSEQS_(this)
  IDList_ SIDEEFFECTS_;                 //< This EffectTable list of side-Effect(s).
  //@access SIDEEFFECTS EffectTable__SIDEEFFECTS_(this)
  Procedure PROCEDURE;
  struct Temporary_ *DEDICATED_;
};
EffectTable_operations— For use by EffectTable_FOREACH_Operation.
static inline IStack
EffectTable_operations(EffectTable this)
{
  return EffectTable_OPERATIONS(this);
}
EffectTable_FOREACH_Operation— Iterate over this EffectTable Operation(s).
#define EffectTable_FOREACH_Operation(this, operation) { \
  IStack EffectTable_OPERATIONS = EffectTable_operations(this); \
  IStack_FOREACH(EffectTable_OPERATIONS, Operation, EffectTable__ITER) { \
    Operation operation = *EffectTable__ITER;
#define EffectTable_ENDEACH_Operation \
  } IStack_ENDEACH; \
}
EffectTable_FORBACK_Operation— Iterate over this EffectTable Operation(s).
#define EffectTable_FORBACK_Operation(this, operation) { \
  IStack EffectTable_OPERATIONS = EffectTable_operations(this); \
  IStack_FORBACK(EffectTable_OPERATIONS, Operation, EffectTable__ITER) { \
    Operation operation = *EffectTable__ITER;
#define EffectTable_ENDBACK_Operation \
  } IStack_ENDBACK; \
}
EffectTable_effectSeqs— For use by EffectTable_FOREACH_EffectSeq.
static inline HTable
EffectTable_effectSeqs(EffectTable this)
{
  return EffectTable_EFFECTSEQS(this);
}
EffectTable_FOREACH_EffectSeq— Iterate over this EffectTable EffectSeq(s).
#define EffectTable_FOREACH_EffectSeq(this, effectSeq) { \
  HTable EffectTable_EFFECTSEQS = EffectTable_effectSeqs(this); \
  HTable_FOREACH(EffectTable_EFFECTSEQS, HTable_KEY, EffectSeq_, effectSeq) { \
    Temporary EffectTable_TEMPORARY = (Temporary)HTable_KEY;
#define EffectTable_ENDEACH_EffectSeq \
  } HTable_ENDEACH; \
}
EffectTable_lookupEffectSeq— Return the EffectSeq associated to temporary.
EffectSeq
EffectTable_lookupEffectSeq(EffectTable this, Temporary temporary);
EffectTable_enterRegisterSetSideEffects— Enter the side Effects of an Operation from a RegisterSet.
void
EffectTable_enterRegisterSetSideEffects(EffectTable this, Operation operation,
                                        const_RegisterSet registerSet, EffectFlags flags);
EffectTable_enterTemporarySetSideEffects— Enter the side Effects of an Operation from a TemporarySet.
void
EffectTable_enterTemporarySetSideEffects(EffectTable this, Operation operation,
                                         TemporarySet temporarySet, EffectFlags flags);
EffectTable_enterOperation— Enter an Operation into this EffectTable.
sideEffects
If true, compute the operation side Effect(s).
void
EffectTable_enterOperation(EffectTable this, Operation operation, bool sideEffects);