ltage.cc revision 13455
111784Sarthur.perais@inria.fr/* 211784Sarthur.perais@inria.fr * Copyright (c) 2014 The University of Wisconsin 311784Sarthur.perais@inria.fr * 411784Sarthur.perais@inria.fr * Copyright (c) 2006 INRIA (Institut National de Recherche en 511784Sarthur.perais@inria.fr * Informatique et en Automatique / French National Research Institute 611784Sarthur.perais@inria.fr * for Computer Science and Applied Mathematics) 711784Sarthur.perais@inria.fr * 811784Sarthur.perais@inria.fr * All rights reserved. 911784Sarthur.perais@inria.fr * 1011784Sarthur.perais@inria.fr * Redistribution and use in source and binary forms, with or without 1111784Sarthur.perais@inria.fr * modification, are permitted provided that the following conditions are 1211784Sarthur.perais@inria.fr * met: redistributions of source code must retain the above copyright 1311784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer; 1411784Sarthur.perais@inria.fr * redistributions in binary form must reproduce the above copyright 1511784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer in the 1611784Sarthur.perais@inria.fr * documentation and/or other materials provided with the distribution; 1711784Sarthur.perais@inria.fr * neither the name of the copyright holders nor the names of its 1811784Sarthur.perais@inria.fr * contributors may be used to endorse or promote products derived from 1911784Sarthur.perais@inria.fr * this software without specific prior written permission. 2011784Sarthur.perais@inria.fr * 2111784Sarthur.perais@inria.fr * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2211784Sarthur.perais@inria.fr * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2311784Sarthur.perais@inria.fr * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2411784Sarthur.perais@inria.fr * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2511784Sarthur.perais@inria.fr * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2611784Sarthur.perais@inria.fr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2711784Sarthur.perais@inria.fr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2811784Sarthur.perais@inria.fr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2911784Sarthur.perais@inria.fr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3011784Sarthur.perais@inria.fr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3111784Sarthur.perais@inria.fr * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3211784Sarthur.perais@inria.fr * 3311784Sarthur.perais@inria.fr * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais, 3411784Sarthur.perais@inria.fr * from André Seznec's code. 3511784Sarthur.perais@inria.fr */ 3611784Sarthur.perais@inria.fr 3711784Sarthur.perais@inria.fr/* @file 3811784Sarthur.perais@inria.fr * Implementation of a L-TAGE branch predictor 3911784Sarthur.perais@inria.fr */ 4011784Sarthur.perais@inria.fr 4111784Sarthur.perais@inria.fr#include "cpu/pred/ltage.hh" 4211784Sarthur.perais@inria.fr 4311784Sarthur.perais@inria.fr#include "base/intmath.hh" 4412334Sgabeblack@google.com#include "base/logging.hh" 4511784Sarthur.perais@inria.fr#include "base/random.hh" 4611784Sarthur.perais@inria.fr#include "base/trace.hh" 4711784Sarthur.perais@inria.fr#include "debug/Fetch.hh" 4811784Sarthur.perais@inria.fr#include "debug/LTage.hh" 4911784Sarthur.perais@inria.fr 5011784Sarthur.perais@inria.frLTAGE::LTAGE(const LTAGEParams *params) 5113454Spau.cabre@metempsy.com : TAGE(params), 5211784Sarthur.perais@inria.fr logSizeLoopPred(params->logSizeLoopPred), 5313442Spau.cabre@metempsy.com loopTableAgeBits(params->loopTableAgeBits), 5413442Spau.cabre@metempsy.com loopTableConfidenceBits(params->loopTableConfidenceBits), 5513442Spau.cabre@metempsy.com loopTableTagBits(params->loopTableTagBits), 5613442Spau.cabre@metempsy.com loopTableIterBits(params->loopTableIterBits), 5713444Spau.cabre@metempsy.com logLoopTableAssoc(params->logLoopTableAssoc), 5813442Spau.cabre@metempsy.com confidenceThreshold((1 << loopTableConfidenceBits) - 1), 5913442Spau.cabre@metempsy.com loopTagMask((1 << loopTableTagBits) - 1), 6013442Spau.cabre@metempsy.com loopNumIterMask((1 << loopTableIterBits) - 1), 6113454Spau.cabre@metempsy.com loopUseCounter(0), 6213444Spau.cabre@metempsy.com withLoopBits(params->withLoopBits) 6311784Sarthur.perais@inria.fr{ 6413442Spau.cabre@metempsy.com // we use uint16_t type for these vales, so they cannot be more than 6513442Spau.cabre@metempsy.com // 16 bits 6613442Spau.cabre@metempsy.com assert(loopTableTagBits <= 16); 6713442Spau.cabre@metempsy.com assert(loopTableIterBits <= 16); 6813442Spau.cabre@metempsy.com 6913444Spau.cabre@metempsy.com assert(logSizeLoopPred >= logLoopTableAssoc); 7013444Spau.cabre@metempsy.com 7111784Sarthur.perais@inria.fr ltable = new LoopEntry[ULL(1) << logSizeLoopPred]; 7211784Sarthur.perais@inria.fr} 7311784Sarthur.perais@inria.fr 7411784Sarthur.perais@inria.frint 7511784Sarthur.perais@inria.frLTAGE::lindex(Addr pc_in) const 7611784Sarthur.perais@inria.fr{ 7713444Spau.cabre@metempsy.com // The loop table is implemented as a linear table 7813444Spau.cabre@metempsy.com // If associativity is N (N being 1 << logLoopTableAssoc), 7913444Spau.cabre@metempsy.com // the first N entries are for set 0, the next N entries are for set 1, 8013444Spau.cabre@metempsy.com // and so on. 8113444Spau.cabre@metempsy.com // Thus, this function calculates the set and then it gets left shifted 8213444Spau.cabre@metempsy.com // by logLoopTableAssoc in order to return the index of the first of the 8313444Spau.cabre@metempsy.com // N entries of the set 8413444Spau.cabre@metempsy.com Addr mask = (ULL(1) << (logSizeLoopPred - logLoopTableAssoc)) - 1; 8513444Spau.cabre@metempsy.com return (((pc_in >> instShiftAmt) & mask) << logLoopTableAssoc); 8611784Sarthur.perais@inria.fr} 8711784Sarthur.perais@inria.fr 8811784Sarthur.perais@inria.fr//loop prediction: only used if high confidence 8911784Sarthur.perais@inria.frbool 9013454Spau.cabre@metempsy.comLTAGE::getLoop(Addr pc, LTageBranchInfo* bi) const 9111784Sarthur.perais@inria.fr{ 9211784Sarthur.perais@inria.fr bi->loopHit = -1; 9311784Sarthur.perais@inria.fr bi->loopPredValid = false; 9411784Sarthur.perais@inria.fr bi->loopIndex = lindex(pc); 9513444Spau.cabre@metempsy.com unsigned pcShift = instShiftAmt + logSizeLoopPred - logLoopTableAssoc; 9613444Spau.cabre@metempsy.com bi->loopTag = ((pc) >> pcShift) & loopTagMask; 9711784Sarthur.perais@inria.fr 9813444Spau.cabre@metempsy.com for (int i = 0; i < (1 << logLoopTableAssoc); i++) { 9911784Sarthur.perais@inria.fr if (ltable[bi->loopIndex + i].tag == bi->loopTag) { 10011784Sarthur.perais@inria.fr bi->loopHit = i; 10113442Spau.cabre@metempsy.com bi->loopPredValid = 10213442Spau.cabre@metempsy.com ltable[bi->loopIndex + i].confidence == confidenceThreshold; 10311784Sarthur.perais@inria.fr bi->currentIter = ltable[bi->loopIndex + i].currentIterSpec; 10411784Sarthur.perais@inria.fr if (ltable[bi->loopIndex + i].currentIterSpec + 1 == 10511784Sarthur.perais@inria.fr ltable[bi->loopIndex + i].numIter) { 10611784Sarthur.perais@inria.fr return !(ltable[bi->loopIndex + i].dir); 10711784Sarthur.perais@inria.fr }else { 10811784Sarthur.perais@inria.fr return (ltable[bi->loopIndex + i].dir); 10911784Sarthur.perais@inria.fr } 11011784Sarthur.perais@inria.fr } 11111784Sarthur.perais@inria.fr } 11211784Sarthur.perais@inria.fr return false; 11311784Sarthur.perais@inria.fr} 11411784Sarthur.perais@inria.fr 11511784Sarthur.perais@inria.frvoid 11613454Spau.cabre@metempsy.comLTAGE::specLoopUpdate(Addr pc, bool taken, LTageBranchInfo* bi) 11711784Sarthur.perais@inria.fr{ 11811784Sarthur.perais@inria.fr if (bi->loopHit>=0) { 11911784Sarthur.perais@inria.fr int index = lindex(pc); 12011784Sarthur.perais@inria.fr if (taken != ltable[index].dir) { 12111784Sarthur.perais@inria.fr ltable[index].currentIterSpec = 0; 12211784Sarthur.perais@inria.fr } else { 12313442Spau.cabre@metempsy.com ltable[index].currentIterSpec = 12413442Spau.cabre@metempsy.com (ltable[index].currentIterSpec + 1) & loopNumIterMask; 12511784Sarthur.perais@inria.fr } 12611784Sarthur.perais@inria.fr } 12711784Sarthur.perais@inria.fr} 12811784Sarthur.perais@inria.fr 12911784Sarthur.perais@inria.frvoid 13013454Spau.cabre@metempsy.comLTAGE::loopUpdate(Addr pc, bool taken, LTageBranchInfo* bi) 13111784Sarthur.perais@inria.fr{ 13211784Sarthur.perais@inria.fr int idx = bi->loopIndex + bi->loopHit; 13311784Sarthur.perais@inria.fr if (bi->loopHit >= 0) { 13411784Sarthur.perais@inria.fr //already a hit 13511784Sarthur.perais@inria.fr if (bi->loopPredValid) { 13611784Sarthur.perais@inria.fr if (taken != bi->loopPred) { 13711784Sarthur.perais@inria.fr // free the entry 13811784Sarthur.perais@inria.fr ltable[idx].numIter = 0; 13911784Sarthur.perais@inria.fr ltable[idx].age = 0; 14011784Sarthur.perais@inria.fr ltable[idx].confidence = 0; 14111784Sarthur.perais@inria.fr ltable[idx].currentIter = 0; 14211784Sarthur.perais@inria.fr return; 14311784Sarthur.perais@inria.fr } else if (bi->loopPred != bi->tagePred) { 14411784Sarthur.perais@inria.fr DPRINTF(LTage, "Loop Prediction success:%lx\n",pc); 14513442Spau.cabre@metempsy.com unsignedCtrUpdate(ltable[idx].age, true, loopTableAgeBits); 14611784Sarthur.perais@inria.fr } 14711784Sarthur.perais@inria.fr } 14811784Sarthur.perais@inria.fr 14913442Spau.cabre@metempsy.com ltable[idx].currentIter = 15013442Spau.cabre@metempsy.com (ltable[idx].currentIter + 1) & loopNumIterMask; 15111784Sarthur.perais@inria.fr if (ltable[idx].currentIter > ltable[idx].numIter) { 15211784Sarthur.perais@inria.fr ltable[idx].confidence = 0; 15311784Sarthur.perais@inria.fr if (ltable[idx].numIter != 0) { 15411784Sarthur.perais@inria.fr // free the entry 15511784Sarthur.perais@inria.fr ltable[idx].numIter = 0; 15611784Sarthur.perais@inria.fr ltable[idx].age = 0; 15711784Sarthur.perais@inria.fr ltable[idx].confidence = 0; 15811784Sarthur.perais@inria.fr } 15911784Sarthur.perais@inria.fr } 16011784Sarthur.perais@inria.fr 16111784Sarthur.perais@inria.fr if (taken != ltable[idx].dir) { 16211784Sarthur.perais@inria.fr if (ltable[idx].currentIter == ltable[idx].numIter) { 16311784Sarthur.perais@inria.fr DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc); 16411784Sarthur.perais@inria.fr 16513442Spau.cabre@metempsy.com unsignedCtrUpdate(ltable[idx].confidence, true, 16613442Spau.cabre@metempsy.com loopTableConfidenceBits); 16711784Sarthur.perais@inria.fr //just do not predict when the loop count is 1 or 2 16811784Sarthur.perais@inria.fr if (ltable[idx].numIter < 3) { 16911784Sarthur.perais@inria.fr // free the entry 17011784Sarthur.perais@inria.fr ltable[idx].dir = taken; 17111784Sarthur.perais@inria.fr ltable[idx].numIter = 0; 17211784Sarthur.perais@inria.fr ltable[idx].age = 0; 17311784Sarthur.perais@inria.fr ltable[idx].confidence = 0; 17411784Sarthur.perais@inria.fr } 17511784Sarthur.perais@inria.fr } else { 17611784Sarthur.perais@inria.fr DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc); 17711784Sarthur.perais@inria.fr if (ltable[idx].numIter == 0) { 17811784Sarthur.perais@inria.fr // first complete nest; 17911784Sarthur.perais@inria.fr ltable[idx].confidence = 0; 18011784Sarthur.perais@inria.fr ltable[idx].numIter = ltable[idx].currentIter; 18111784Sarthur.perais@inria.fr } else { 18211784Sarthur.perais@inria.fr //not the same number of iterations as last time: free the 18311784Sarthur.perais@inria.fr //entry 18411784Sarthur.perais@inria.fr ltable[idx].numIter = 0; 18511784Sarthur.perais@inria.fr ltable[idx].age = 0; 18611784Sarthur.perais@inria.fr ltable[idx].confidence = 0; 18711784Sarthur.perais@inria.fr } 18811784Sarthur.perais@inria.fr } 18911784Sarthur.perais@inria.fr ltable[idx].currentIter = 0; 19011784Sarthur.perais@inria.fr } 19111784Sarthur.perais@inria.fr 19211784Sarthur.perais@inria.fr } else if (taken) { 19311784Sarthur.perais@inria.fr //try to allocate an entry on taken branch 19411784Sarthur.perais@inria.fr int nrand = random_mt.random<int>(); 19513444Spau.cabre@metempsy.com for (int i = 0; i < (1 << logLoopTableAssoc); i++) { 19613444Spau.cabre@metempsy.com int loop_hit = (nrand + i) & ((1 << logLoopTableAssoc) - 1); 19711784Sarthur.perais@inria.fr idx = bi->loopIndex + loop_hit; 19811784Sarthur.perais@inria.fr if (ltable[idx].age == 0) { 19911784Sarthur.perais@inria.fr DPRINTF(LTage, "Allocating loop pred entry for branch %lx\n", 20011784Sarthur.perais@inria.fr pc); 20111784Sarthur.perais@inria.fr ltable[idx].dir = !taken; 20211784Sarthur.perais@inria.fr ltable[idx].tag = bi->loopTag; 20311784Sarthur.perais@inria.fr ltable[idx].numIter = 0; 20413442Spau.cabre@metempsy.com ltable[idx].age = (1 << loopTableAgeBits) - 1; 20511784Sarthur.perais@inria.fr ltable[idx].confidence = 0; 20611784Sarthur.perais@inria.fr ltable[idx].currentIter = 1; 20711784Sarthur.perais@inria.fr break; 20811784Sarthur.perais@inria.fr 20911784Sarthur.perais@inria.fr } 21011784Sarthur.perais@inria.fr else 21111784Sarthur.perais@inria.fr ltable[idx].age--; 21211784Sarthur.perais@inria.fr } 21311784Sarthur.perais@inria.fr } 21411784Sarthur.perais@inria.fr 21511784Sarthur.perais@inria.fr} 21611784Sarthur.perais@inria.fr 21711784Sarthur.perais@inria.fr//prediction 21811784Sarthur.perais@inria.frbool 21911784Sarthur.perais@inria.frLTAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) 22011784Sarthur.perais@inria.fr{ 22113454Spau.cabre@metempsy.com LTageBranchInfo *bi = new LTageBranchInfo(nHistoryTables+1); 22211784Sarthur.perais@inria.fr b = (void*)(bi); 22313454Spau.cabre@metempsy.com 22413454Spau.cabre@metempsy.com bool pred_taken = tagePredict(tid, branch_pc, cond_branch, bi); 22511784Sarthur.perais@inria.fr 22611784Sarthur.perais@inria.fr if (cond_branch) { 22713454Spau.cabre@metempsy.com bi->loopPred = getLoop(branch_pc, bi); // loop prediction 22811784Sarthur.perais@inria.fr 22913454Spau.cabre@metempsy.com if ((loopUseCounter >= 0) && bi->loopPredValid) { 23013454Spau.cabre@metempsy.com pred_taken = bi->loopPred; 23113455Spau.cabre@metempsy.com bi->provider = LOOP; 23211784Sarthur.perais@inria.fr } 23311784Sarthur.perais@inria.fr DPRINTF(LTage, "Predict for %lx: taken?:%d, loopTaken?:%d, " 23411784Sarthur.perais@inria.fr "loopValid?:%d, loopUseCounter:%d, tagePred:%d, altPred:%d\n", 23511784Sarthur.perais@inria.fr branch_pc, pred_taken, bi->loopPred, bi->loopPredValid, 23611784Sarthur.perais@inria.fr loopUseCounter, bi->tagePred, bi->altTaken); 23711784Sarthur.perais@inria.fr } 23813454Spau.cabre@metempsy.com 23911784Sarthur.perais@inria.fr specLoopUpdate(branch_pc, pred_taken, bi); 24011784Sarthur.perais@inria.fr return pred_taken; 24111784Sarthur.perais@inria.fr} 24211784Sarthur.perais@inria.fr 24311784Sarthur.perais@inria.frvoid 24413454Spau.cabre@metempsy.comLTAGE::condBranchUpdate(Addr branch_pc, bool taken, 24513454Spau.cabre@metempsy.com TageBranchInfo* tage_bi, int nrand) 24611784Sarthur.perais@inria.fr{ 24713454Spau.cabre@metempsy.com LTageBranchInfo* bi = static_cast<LTageBranchInfo*>(tage_bi); 24811784Sarthur.perais@inria.fr 24913454Spau.cabre@metempsy.com // first update the loop predictor 25013454Spau.cabre@metempsy.com loopUpdate(branch_pc, taken, bi); 25111784Sarthur.perais@inria.fr 25213454Spau.cabre@metempsy.com if (bi->loopPredValid) { 25313454Spau.cabre@metempsy.com if (bi->tagePred != bi->loopPred) { 25413454Spau.cabre@metempsy.com ctrUpdate(loopUseCounter, 25513454Spau.cabre@metempsy.com (bi->loopPred == taken), 25613454Spau.cabre@metempsy.com withLoopBits); 25713454Spau.cabre@metempsy.com } 25811784Sarthur.perais@inria.fr } 25911784Sarthur.perais@inria.fr 26013454Spau.cabre@metempsy.com TAGE::condBranchUpdate(branch_pc, taken, bi, nrand); 26111784Sarthur.perais@inria.fr} 26211784Sarthur.perais@inria.fr 26311784Sarthur.perais@inria.frvoid 26411784Sarthur.perais@inria.frLTAGE::squash(ThreadID tid, bool taken, void *bp_history) 26511784Sarthur.perais@inria.fr{ 26613454Spau.cabre@metempsy.com TAGE::squash(tid, taken, bp_history); 26713454Spau.cabre@metempsy.com 26813454Spau.cabre@metempsy.com LTageBranchInfo* bi = (LTageBranchInfo*)(bp_history); 26911784Sarthur.perais@inria.fr 27011784Sarthur.perais@inria.fr if (bi->condBranch) { 27111784Sarthur.perais@inria.fr if (bi->loopHit >= 0) { 27211784Sarthur.perais@inria.fr int idx = bi->loopIndex + bi->loopHit; 27311784Sarthur.perais@inria.fr ltable[idx].currentIterSpec = bi->currentIter; 27411784Sarthur.perais@inria.fr } 27511784Sarthur.perais@inria.fr } 27611784Sarthur.perais@inria.fr} 27711784Sarthur.perais@inria.fr 27811784Sarthur.perais@inria.frvoid 27911784Sarthur.perais@inria.frLTAGE::squash(ThreadID tid, void *bp_history) 28011784Sarthur.perais@inria.fr{ 28113454Spau.cabre@metempsy.com LTageBranchInfo* bi = (LTageBranchInfo*)(bp_history); 28211784Sarthur.perais@inria.fr if (bi->condBranch) { 28311784Sarthur.perais@inria.fr if (bi->loopHit >= 0) { 28411784Sarthur.perais@inria.fr int idx = bi->loopIndex + bi->loopHit; 28511784Sarthur.perais@inria.fr ltable[idx].currentIterSpec = bi->currentIter; 28611784Sarthur.perais@inria.fr } 28711784Sarthur.perais@inria.fr } 28811784Sarthur.perais@inria.fr 28913454Spau.cabre@metempsy.com TAGE::squash(tid, bp_history); 29011784Sarthur.perais@inria.fr} 29111784Sarthur.perais@inria.fr 29213455Spau.cabre@metempsy.com 29313455Spau.cabre@metempsy.comvoid 29413455Spau.cabre@metempsy.comLTAGE::updateStats(bool taken, TageBranchInfo* bi) 29513455Spau.cabre@metempsy.com{ 29613455Spau.cabre@metempsy.com TAGE::updateStats(taken, bi); 29713455Spau.cabre@metempsy.com 29813455Spau.cabre@metempsy.com LTageBranchInfo * ltage_bi = static_cast<LTageBranchInfo *>(bi); 29913455Spau.cabre@metempsy.com 30013455Spau.cabre@metempsy.com if (ltage_bi->provider == LOOP) { 30113455Spau.cabre@metempsy.com if (taken == ltage_bi->loopPred) { 30213455Spau.cabre@metempsy.com loopPredictorCorrect++; 30313455Spau.cabre@metempsy.com } else { 30413455Spau.cabre@metempsy.com loopPredictorWrong++; 30513455Spau.cabre@metempsy.com } 30613455Spau.cabre@metempsy.com } 30713455Spau.cabre@metempsy.com} 30813455Spau.cabre@metempsy.com 30913455Spau.cabre@metempsy.com 31013455Spau.cabre@metempsy.com 31113455Spau.cabre@metempsy.comvoid 31213455Spau.cabre@metempsy.comLTAGE::regStats() 31313455Spau.cabre@metempsy.com{ 31413455Spau.cabre@metempsy.com TAGE::regStats(); 31513455Spau.cabre@metempsy.com 31613455Spau.cabre@metempsy.com loopPredictorCorrect 31713455Spau.cabre@metempsy.com .name(name() + ".loopPredictorCorrect") 31813455Spau.cabre@metempsy.com .desc("Number of times the loop predictor is the provider and " 31913455Spau.cabre@metempsy.com "the prediction is correct"); 32013455Spau.cabre@metempsy.com 32113455Spau.cabre@metempsy.com loopPredictorWrong 32213455Spau.cabre@metempsy.com .name(name() + ".loopPredictorWrong") 32313455Spau.cabre@metempsy.com .desc("Number of times the loop predictor is the provier and " 32413455Spau.cabre@metempsy.com "the prediction is wrong"); 32513455Spau.cabre@metempsy.com} 32613455Spau.cabre@metempsy.com 32713455Spau.cabre@metempsy.com 32813455Spau.cabre@metempsy.com 32911784Sarthur.perais@inria.frLTAGE* 33011784Sarthur.perais@inria.frLTAGEParams::create() 33111784Sarthur.perais@inria.fr{ 33211784Sarthur.perais@inria.fr return new LTAGE(this); 33311784Sarthur.perais@inria.fr} 334