1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceInstVarIter.h - Iterate over inst vars ----*- C++ -*-===// 2*03ce13f7SAndroid Build Coastguard Worker // 3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator 4*03ce13f7SAndroid Build Coastguard Worker // 5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker /// 10*03ce13f7SAndroid Build Coastguard Worker /// \file 11*03ce13f7SAndroid Build Coastguard Worker /// \brief Defines a common pattern for iterating over the variables of an 12*03ce13f7SAndroid Build Coastguard Worker /// instruction. 13*03ce13f7SAndroid Build Coastguard Worker /// 14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 15*03ce13f7SAndroid Build Coastguard Worker 16*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEINSTVARITER_H 17*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEINSTVARITER_H 18*03ce13f7SAndroid Build Coastguard Worker 19*03ce13f7SAndroid Build Coastguard Worker /// In Subzero, an Instr may have multiple Ice::Operands, and each Operand can 20*03ce13f7SAndroid Build Coastguard Worker /// have zero, one, or more Variables. 21*03ce13f7SAndroid Build Coastguard Worker /// 22*03ce13f7SAndroid Build Coastguard Worker /// We found that a common pattern in Subzero is to iterate over all the 23*03ce13f7SAndroid Build Coastguard Worker /// Variables in an Instruction. This led to the following pattern being 24*03ce13f7SAndroid Build Coastguard Worker /// repeated multiple times across the codebase: 25*03ce13f7SAndroid Build Coastguard Worker /// 26*03ce13f7SAndroid Build Coastguard Worker /// for (Operand Op : Instr.Operands()) 27*03ce13f7SAndroid Build Coastguard Worker /// for (Variable Var : Op.Vars()) 28*03ce13f7SAndroid Build Coastguard Worker /// do_my_thing(Var, Instr) 29*03ce13f7SAndroid Build Coastguard Worker /// 30*03ce13f7SAndroid Build Coastguard Worker /// 31*03ce13f7SAndroid Build Coastguard Worker /// This code is straightforward, but one may take a couple of seconds to 32*03ce13f7SAndroid Build Coastguard Worker /// identify what it is doing. We therefore introduce a macroized iterator for 33*03ce13f7SAndroid Build Coastguard Worker /// hiding this common idiom behind a more explicit interface. 34*03ce13f7SAndroid Build Coastguard Worker /// 35*03ce13f7SAndroid Build Coastguard Worker /// FOREACH_VAR_IN_INST(Var, Instr) provides this interface. Its first argument 36*03ce13f7SAndroid Build Coastguard Worker /// needs to be a valid C++ identifier currently undeclared in the current 37*03ce13f7SAndroid Build Coastguard Worker /// scope; Instr can be any expression yielding a Ice::Inst&&. Even though its 38*03ce13f7SAndroid Build Coastguard Worker /// definition is ugly, awful, painful-to-read, using it is fairly simple: 39*03ce13f7SAndroid Build Coastguard Worker /// 40*03ce13f7SAndroid Build Coastguard Worker /// FOREACH_VAR_IN_INST(Var, Instr) 41*03ce13f7SAndroid Build Coastguard Worker /// do_my_thing(Var, Instr) 42*03ce13f7SAndroid Build Coastguard Worker /// 43*03ce13f7SAndroid Build Coastguard Worker /// If your loop body contains more than one statement, you can wrap it with a 44*03ce13f7SAndroid Build Coastguard Worker /// {}, just like any other C++ statement. Note that doing 45*03ce13f7SAndroid Build Coastguard Worker /// 46*03ce13f7SAndroid Build Coastguard Worker /// FOREACH_VAR_IN_INST(Var0, Instr0) 47*03ce13f7SAndroid Build Coastguard Worker /// FOREACH_VAR_IN_INST(Var1, Instr1) 48*03ce13f7SAndroid Build Coastguard Worker /// 49*03ce13f7SAndroid Build Coastguard Worker /// is perfectly safe and legal -- as long as Var0 and Var1 are different 50*03ce13f7SAndroid Build Coastguard Worker /// identifiers. 51*03ce13f7SAndroid Build Coastguard Worker /// 52*03ce13f7SAndroid Build Coastguard Worker /// It is sometimes useful to know Var's index in Instr, which can be obtained 53*03ce13f7SAndroid Build Coastguard Worker /// with 54*03ce13f7SAndroid Build Coastguard Worker /// 55*03ce13f7SAndroid Build Coastguard Worker /// IndexOfVarInInst(Var) 56*03ce13f7SAndroid Build Coastguard Worker /// 57*03ce13f7SAndroid Build Coastguard Worker /// Similarly, the current Variable's Operand index can be obtained with 58*03ce13f7SAndroid Build Coastguard Worker /// 59*03ce13f7SAndroid Build Coastguard Worker /// IndexOfVarOperandInInst(Var). 60*03ce13f7SAndroid Build Coastguard Worker /// 61*03ce13f7SAndroid Build Coastguard Worker /// And that's pretty much it. Now, if you really hate yourself, keep reading, 62*03ce13f7SAndroid Build Coastguard Worker /// but beware! The iterator implementation abuses comma operators, for 63*03ce13f7SAndroid Build Coastguard Worker /// statements, variable initialization and expression evaluations. You have 64*03ce13f7SAndroid Build Coastguard Worker /// been warned. 65*03ce13f7SAndroid Build Coastguard Worker /// 66*03ce13f7SAndroid Build Coastguard Worker /// **Implementation details** 67*03ce13f7SAndroid Build Coastguard Worker /// 68*03ce13f7SAndroid Build Coastguard Worker /// First, let's "break" the two loops into multiple parts: 69*03ce13f7SAndroid Build Coastguard Worker /// 70*03ce13f7SAndroid Build Coastguard Worker /// for ( Init1; Cond1; Step1 ) 71*03ce13f7SAndroid Build Coastguard Worker /// if ( CondIf ) 72*03ce13f7SAndroid Build Coastguard Worker /// UnreachableThenBody 73*03ce13f7SAndroid Build Coastguard Worker /// else 74*03ce13f7SAndroid Build Coastguard Worker /// for ( Init2; Cond2; Step2 ) 75*03ce13f7SAndroid Build Coastguard Worker /// 76*03ce13f7SAndroid Build Coastguard Worker /// The hairiest, scariest, most confusing parts here are Init2 and Cond2, so 77*03ce13f7SAndroid Build Coastguard Worker /// let's save them for later. 78*03ce13f7SAndroid Build Coastguard Worker /// 79*03ce13f7SAndroid Build Coastguard Worker /// 1) Init1 declares five integer variables: 80*03ce13f7SAndroid Build Coastguard Worker /// * i --> outer loop control variable; 81*03ce13f7SAndroid Build Coastguard Worker /// * Var##Index --> the current variable index 82*03ce13f7SAndroid Build Coastguard Worker /// * SrcSize --> how many operands does Instr have? 83*03ce13f7SAndroid Build Coastguard Worker /// * j --> the inner loop control variable 84*03ce13f7SAndroid Build Coastguard Worker /// * NumVars --> how many variables does the current operand have? 85*03ce13f7SAndroid Build Coastguard Worker /// 86*03ce13f7SAndroid Build Coastguard Worker /// 2) Cond1 and Step1 are your typical for condition and step expressions. 87*03ce13f7SAndroid Build Coastguard Worker /// 88*03ce13f7SAndroid Build Coastguard Worker /// 3) CondIf is where the voodoo starts. We abuse CondIf to declare a local 89*03ce13f7SAndroid Build Coastguard Worker /// Operand * variable to hold the current operand being evaluated to avoid 90*03ce13f7SAndroid Build Coastguard Worker /// invoking an Instr::getOperand for each outter loop iteration -- which 91*03ce13f7SAndroid Build Coastguard Worker /// caused a small performance regression. We initialize the Operand * 92*03ce13f7SAndroid Build Coastguard Worker /// variable with nullptr, so UnreachableThenBody is trully unreachable, and 93*03ce13f7SAndroid Build Coastguard Worker /// use the else statement to declare the inner loop. We want to use an else 94*03ce13f7SAndroid Build Coastguard Worker /// here to prevent code like 95*03ce13f7SAndroid Build Coastguard Worker /// 96*03ce13f7SAndroid Build Coastguard Worker /// FOREACH_VAR_IN_INST(Var, Instr) { 97*03ce13f7SAndroid Build Coastguard Worker /// } else { 98*03ce13f7SAndroid Build Coastguard Worker /// } 99*03ce13f7SAndroid Build Coastguard Worker /// 100*03ce13f7SAndroid Build Coastguard Worker /// from being legal. We also want to avoid warnings about "dangling else"s. 101*03ce13f7SAndroid Build Coastguard Worker /// 102*03ce13f7SAndroid Build Coastguard Worker /// 4) Init2 is where the voodoo starts. It declares a Variable * local 103*03ce13f7SAndroid Build Coastguard Worker /// variable name 'Var' (i.e., whatever identifier the first parameter to 104*03ce13f7SAndroid Build Coastguard Worker /// FOREACH_VAR_IN_INST is), and initializes it with nullptr. Why nullptr? 105*03ce13f7SAndroid Build Coastguard Worker /// Because as stated above, some operands have zero Variables, and therefore 106*03ce13f7SAndroid Build Coastguard Worker /// initializing Var = CurrentOperand->Variable(0) would lead to an assertion. 107*03ce13f7SAndroid Build Coastguard Worker /// Init2 is also required to initialize the control variables used in Cond2, 108*03ce13f7SAndroid Build Coastguard Worker /// as well as the current Operand * holder, Therefore, we use the obscure 109*03ce13f7SAndroid Build Coastguard Worker /// comma operator to initialize Var, and the control variables. The 110*03ce13f7SAndroid Build Coastguard Worker /// declaration 111*03ce13f7SAndroid Build Coastguard Worker /// 112*03ce13f7SAndroid Build Coastguard Worker /// Variable *Var = (j = 0, CurrentOperand = Instr.Operand[i], 113*03ce13f7SAndroid Build Coastguard Worker /// NumVars = CurrentOperand.NumVars, nullptr) 114*03ce13f7SAndroid Build Coastguard Worker /// 115*03ce13f7SAndroid Build Coastguard Worker /// achieves that. 116*03ce13f7SAndroid Build Coastguard Worker /// 117*03ce13f7SAndroid Build Coastguard Worker /// 5) Cond2 is where we lose all hopes of having a self-documenting 118*03ce13f7SAndroid Build Coastguard Worker /// implementation. The stop condition for the inner loop is simply 119*03ce13f7SAndroid Build Coastguard Worker /// 120*03ce13f7SAndroid Build Coastguard Worker /// j < NumVars 121*03ce13f7SAndroid Build Coastguard Worker /// 122*03ce13f7SAndroid Build Coastguard Worker /// But there is one more thing we need to do before jumping to the iterator's 123*03ce13f7SAndroid Build Coastguard Worker /// body: we need to initialize Var with the current variable, but only if the 124*03ce13f7SAndroid Build Coastguard Worker /// loop has not terminated. So we implemented Cond2 in a way that it would 125*03ce13f7SAndroid Build Coastguard Worker /// make Var point to the current Variable, but only if there were more 126*03ce13f7SAndroid Build Coastguard Worker /// variables. So Cond2 became: 127*03ce13f7SAndroid Build Coastguard Worker /// 128*03ce13f7SAndroid Build Coastguard Worker /// j < NumVars && (Var = CurrentOperand.Var[j]) 129*03ce13f7SAndroid Build Coastguard Worker /// 130*03ce13f7SAndroid Build Coastguard Worker /// which is not quite right. Cond2 would evaluate to false if 131*03ce13f7SAndroid Build Coastguard Worker /// CurrentOperand.Var[j] == nullptr. Even though that should never happen in 132*03ce13f7SAndroid Build Coastguard Worker /// Subzero, assuming this is always true is dangerous and could lead to 133*03ce13f7SAndroid Build Coastguard Worker /// problems in the future. So we abused the comma operator one more time here: 134*03ce13f7SAndroid Build Coastguard Worker /// 135*03ce13f7SAndroid Build Coastguard Worker /// j < NumVars && ((Var = CurrentOperand.Var[j]), true) 136*03ce13f7SAndroid Build Coastguard Worker /// 137*03ce13f7SAndroid Build Coastguard Worker /// this expression will evaluate to true if, and only if, j < NumVars. 138*03ce13f7SAndroid Build Coastguard Worker /// 139*03ce13f7SAndroid Build Coastguard Worker /// 6) Step2 increments the inner loop's control variable, as well as the 140*03ce13f7SAndroid Build Coastguard Worker /// current variable index. 141*03ce13f7SAndroid Build Coastguard Worker /// 142*03ce13f7SAndroid Build Coastguard Worker /// We use Var -- which should be a valid C++ identifier -- to uniquify names 143*03ce13f7SAndroid Build Coastguard Worker /// -- e.g., i##Var instead of simply i because we want users to be able to use 144*03ce13f7SAndroid Build Coastguard Worker /// the iterator for cross-products involving instructions' variables. 145*03ce13f7SAndroid Build Coastguard Worker #define FOREACH_VAR_IN_INST(Var, Instr) \ 146*03ce13f7SAndroid Build Coastguard Worker for (SizeT Sz_I##Var##_ = 0, Sz_##Var##Index_ = 0, \ 147*03ce13f7SAndroid Build Coastguard Worker Sz_SrcSize##Var##_ = (Instr).getSrcSize(), Sz_J##Var##_ = 0, \ 148*03ce13f7SAndroid Build Coastguard Worker Sz_NumVars##Var##_ = 0, Sz_Foreach_Break = 0; \ 149*03ce13f7SAndroid Build Coastguard Worker !Sz_Foreach_Break && Sz_I##Var##_ < Sz_SrcSize##Var##_; ++Sz_I##Var##_) \ 150*03ce13f7SAndroid Build Coastguard Worker if (Operand *Sz_Op##Var##_ = nullptr) \ 151*03ce13f7SAndroid Build Coastguard Worker /*nothing*/; \ 152*03ce13f7SAndroid Build Coastguard Worker else \ 153*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var = \ 154*03ce13f7SAndroid Build Coastguard Worker (Sz_J##Var##_ = 0, \ 155*03ce13f7SAndroid Build Coastguard Worker Sz_Op##Var##_ = (Instr).getSrc(Sz_I##Var##_), \ 156*03ce13f7SAndroid Build Coastguard Worker Sz_NumVars##Var##_ = Sz_Op##Var##_->getNumVars(), nullptr); \ 157*03ce13f7SAndroid Build Coastguard Worker !Sz_Foreach_Break && Sz_J##Var##_ < Sz_NumVars##Var##_ && \ 158*03ce13f7SAndroid Build Coastguard Worker ((Var = Sz_Op##Var##_->getVar(Sz_J##Var##_)), true); \ 159*03ce13f7SAndroid Build Coastguard Worker ++Sz_J##Var##_, ++Sz_##Var##Index_) 160*03ce13f7SAndroid Build Coastguard Worker 161*03ce13f7SAndroid Build Coastguard Worker #define IsOnlyValidInFOREACH_VAR_IN_INST(V) \ 162*03ce13f7SAndroid Build Coastguard Worker (static_cast<const SizeT>(Sz_##V##_)) 163*03ce13f7SAndroid Build Coastguard Worker #define IndexOfVarInInst(Var) IsOnlyValidInFOREACH_VAR_IN_INST(Var##Index) 164*03ce13f7SAndroid Build Coastguard Worker #define IndexOfVarOperandInInst(Var) IsOnlyValidInFOREACH_VAR_IN_INST(I##Var) 165*03ce13f7SAndroid Build Coastguard Worker #define FOREACH_VAR_IN_INST_BREAK \ 166*03ce13f7SAndroid Build Coastguard Worker if (true) { \ 167*03ce13f7SAndroid Build Coastguard Worker Sz_Foreach_Break = 1; \ 168*03ce13f7SAndroid Build Coastguard Worker continue; \ 169*03ce13f7SAndroid Build Coastguard Worker } else { \ 170*03ce13f7SAndroid Build Coastguard Worker } 171*03ce13f7SAndroid Build Coastguard Worker #undef OnlyValidIn_FOREACH_VAR_IN_INSTS 172*03ce13f7SAndroid Build Coastguard Worker 173*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEINSTVARITER_H 174