ConstantFolder.h revision ae3a0be92e33bc716722aa600983fc1535acb122
11e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//===-- llvm/Support/ConstantFolder.h - Constant folding helper -*- C++ -*-===// 21e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// 31e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// The LLVM Compiler Infrastructure 41e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// 51e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// This file is distributed under the University of Illinois Open Source 61e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// License. See LICENSE.TXT for details. 71e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// 81e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//===----------------------------------------------------------------------===// 91e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// 1020df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// This file defines the ConstantFolder class, a helper for IRBuilder. 1120df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// It provides IRBuilder with a set of methods for creating constants 1220df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// with minimal folding. For general constant creation and folding, 1320df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. 141e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// 151e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//===----------------------------------------------------------------------===// 161e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 171e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#ifndef LLVM_SUPPORT_CONSTANTFOLDER_H 181e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#define LLVM_SUPPORT_CONSTANTFOLDER_H 191e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 201e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#include "llvm/Constants.h" 211e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 221e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sandsnamespace llvm { 231e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 241e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands/// ConstantFolder - Create constants with minimum, target independent, folding. 251e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sandsclass ConstantFolder { 261e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sandspublic: 271e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 281e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 291e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands // Binary Operators 301e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 311e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 321e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateAdd(Constant *LHS, Constant *RHS) const { 331e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getAdd(LHS, RHS); 341e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 35ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { 36ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman return ConstantExpr::getFAdd(LHS, RHS); 37ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman } 381e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateSub(Constant *LHS, Constant *RHS) const { 391e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getSub(LHS, RHS); 401e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 41ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman Constant *CreateFSub(Constant *LHS, Constant *RHS) const { 42ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman return ConstantExpr::getFSub(LHS, RHS); 43ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman } 441e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateMul(Constant *LHS, Constant *RHS) const { 451e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getMul(LHS, RHS); 461e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 47ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman Constant *CreateFMul(Constant *LHS, Constant *RHS) const { 48ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman return ConstantExpr::getFMul(LHS, RHS); 49ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman } 501e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { 511e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getUDiv(LHS, RHS); 521e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 531e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { 541e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getSDiv(LHS, RHS); 551e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 561e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { 571e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getFDiv(LHS, RHS); 581e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 591e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateURem(Constant *LHS, Constant *RHS) const { 601e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getURem(LHS, RHS); 611e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 621e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateSRem(Constant *LHS, Constant *RHS) const { 631e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getSRem(LHS, RHS); 641e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 651e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateFRem(Constant *LHS, Constant *RHS) const { 661e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getFRem(LHS, RHS); 671e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 681e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateShl(Constant *LHS, Constant *RHS) const { 691e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getShl(LHS, RHS); 701e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 711e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateLShr(Constant *LHS, Constant *RHS) const { 721e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getLShr(LHS, RHS); 731e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 741e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateAShr(Constant *LHS, Constant *RHS) const { 751e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getAShr(LHS, RHS); 761e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 771e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateAnd(Constant *LHS, Constant *RHS) const { 781e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getAnd(LHS, RHS); 791e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 801e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateOr(Constant *LHS, Constant *RHS) const { 811e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getOr(LHS, RHS); 821e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 831e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateXor(Constant *LHS, Constant *RHS) const { 841e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getXor(LHS, RHS); 851e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 861e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 871e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateBinOp(Instruction::BinaryOps Opc, 881e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *LHS, Constant *RHS) const { 891e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::get(Opc, LHS, RHS); 901e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 911e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 921e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 931e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands // Unary Operators 941e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 951e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 961e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateNeg(Constant *C) const { 971e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getNeg(C); 981e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 99ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman Constant *CreateFNeg(Constant *C) const { 100ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman return ConstantExpr::getFNeg(C); 101ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman } 1021e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateNot(Constant *C) const { 1031e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getNot(C); 1041e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1051e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1061e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1071e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands // Memory Instructions 1081e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1091e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1101e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, 1111e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands unsigned NumIdx) const { 1121e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); 1131e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1141e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList, 1151e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands unsigned NumIdx) const { 1161e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); 1171e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1181e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1191e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1201e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands // Cast/Conversion Operators 1211e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1221e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1231e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateCast(Instruction::CastOps Op, Constant *C, 1241e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands const Type *DestTy) const { 1251e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getCast(Op, C, DestTy); 1261e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1271e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateIntCast(Constant *C, const Type *DestTy, 1281e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands bool isSigned) const { 1291e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getIntegerCast(C, DestTy, isSigned); 1301e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1311e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1321e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateBitCast(Constant *C, const Type *DestTy) const { 1331e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return CreateCast(Instruction::BitCast, C, DestTy); 1341e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1351e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const { 1361e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return CreateCast(Instruction::IntToPtr, C, DestTy); 1371e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1381e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const { 1391e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return CreateCast(Instruction::PtrToInt, C, DestTy); 1401e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1411e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { 1421e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getTruncOrBitCast(C, DestTy); 1431e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1441e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1451e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1461e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands // Compare Instructions 1471e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1481e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 149fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, 150fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *RHS) const { 151fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands return ConstantExpr::getCompare(P, LHS, RHS); 152fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands } 153fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 154fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *RHS) const { 155fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands return ConstantExpr::getCompare(P, LHS, RHS); 156fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands } 157fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *CreateVICmp(CmpInst::Predicate P, Constant *LHS, 158fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *RHS) const { 159fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands return ConstantExpr::getCompare(P, LHS, RHS); 160fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands } 161fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *CreateVFCmp(CmpInst::Predicate P, Constant *LHS, 162fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands Constant *RHS) const { 1631e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getCompare(P, LHS, RHS); 1641e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1651e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1661e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1671e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands // Other Instructions 1681e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands //===--------------------------------------------------------------------===// 1691e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1701e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { 1711e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getSelect(C, True, False); 1721e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1731e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1741e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { 1751e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getExtractElement(Vec, Idx); 1761e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1771e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1781e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, 1791e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *Idx) const { 1801e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getInsertElement(Vec, NewElt, Idx); 1811e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1821e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1831e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateShuffleVector(Constant *V1, Constant *V2, 1841e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *Mask) const { 1851e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getShuffleVector(V1, V2, Mask); 1861e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1871e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1881e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateExtractValue(Constant *Agg, const unsigned *IdxList, 1891e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands unsigned NumIdx) const { 1901e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getExtractValue(Agg, IdxList, NumIdx); 1911e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1921e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1931e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands Constant *CreateInsertValue(Constant *Agg, Constant *Val, 1941e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands const unsigned *IdxList, unsigned NumIdx) const { 1951e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands return ConstantExpr::getInsertValue(Agg, Val, IdxList, NumIdx); 1961e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands } 1971e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands}; 1981e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 1991e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands} 2001e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands 2011e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#endif 202