26#include "llvm/Config/llvm-config.h"
43#define DEBUG_TYPE "hsdr"
55 cl::desc(
"Maximum number of split partitions"));
57 cl::desc(
"Do not split loads or stores"));
70 return "Hexagon Split Double Registers";
89 using USet = std::set<unsigned>;
90 using UUSetMap = std::map<unsigned, USet>;
91 using UUPair = std::pair<unsigned, unsigned>;
92 using UUPairMap = std::map<unsigned, UUPair>;
93 using LoopRegMap = std::map<const MachineLoop *, USet>;
95 bool isInduction(
unsigned Reg, LoopRegMap &IRM)
const;
98 void partitionRegisters(UUSetMap &P2Rs);
101 bool isProfitable(
const USet &Part, LoopRegMap &IRM)
const;
103 void collectIndRegsForLoop(
const MachineLoop *L, USet &Rs);
104 void collectIndRegs(LoopRegMap &IRM);
107 const UUPairMap &PairMap,
unsigned SubR);
115 void replaceSubregUses(
MachineInstr *
MI,
const UUPairMap &PairMap);
116 void collapseRegPairs(
MachineInstr *
MI,
const UUPairMap &PairMap);
117 bool splitPartition(
const USet &Part);
121 static void dump_partition(
raw_ostream&,
const USet&,
127char HexagonSplitDoubleRegs::ID;
128int HexagonSplitDoubleRegs::Counter = 0;
130 &Hexagon::DoubleRegsRegClass;
133 "Hexagon Split Double Registers",
false,
false)
135#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
145bool HexagonSplitDoubleRegs::isInduction(
unsigned Reg, LoopRegMap &IRM)
const {
147 const USet &Rs =
I.second;
148 if (Rs.find(Reg) != Rs.end())
154bool HexagonSplitDoubleRegs::isVolatileInstr(
const MachineInstr *
MI)
const {
155 for (
auto &MO :
MI->memoperands())
156 if (MO->isVolatile() || MO->isAtomic())
161bool HexagonSplitDoubleRegs::isFixedInstr(
const MachineInstr *
MI)
const {
162 if (
MI->mayLoadOrStore())
165 if (
MI->isDebugInstr())
168 unsigned Opc =
MI->getOpcode();
173 case TargetOpcode::PHI:
174 case TargetOpcode::COPY:
177 case Hexagon::L2_loadrd_io:
179 if (
MI->getOperand(1).isReg())
182 case Hexagon::S2_storerd_io:
184 if (
MI->getOperand(0).isReg())
187 case Hexagon::L2_loadrd_pi:
188 case Hexagon::S2_storerd_pi:
190 case Hexagon::A2_tfrpi:
191 case Hexagon::A2_combineii:
192 case Hexagon::A4_combineir:
193 case Hexagon::A4_combineii:
194 case Hexagon::A4_combineri:
195 case Hexagon::A2_combinew:
196 case Hexagon::CONST64:
198 case Hexagon::A2_sxtw:
200 case Hexagon::A2_andp:
201 case Hexagon::A2_orp:
202 case Hexagon::A2_xorp:
203 case Hexagon::S2_asl_i_p_or:
204 case Hexagon::S2_asl_i_p:
205 case Hexagon::S2_asr_i_p:
206 case Hexagon::S2_lsr_i_p:
210 for (
auto &
Op :
MI->operands()) {
220void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) {
221 using UUMap = std::map<unsigned, unsigned>;
222 using UVect = std::vector<unsigned>;
224 unsigned NumRegs =
MRI->getNumVirtRegs();
226 for (
unsigned i = 0; i < NumRegs; ++i) {
228 if (
MRI->getRegClass(R) == DoubleRC)
239 if (!DefI || isFixedInstr(DefI))
249 USet &Asc = AssocMap[
R];
250 for (
auto U =
MRI->use_nodbg_begin(R), Z =
MRI->use_nodbg_end();
254 if (isFixedInstr(UseI))
258 if (&MO == &
Op || !MO.isReg() || MO.getSubReg())
261 if (!
T.isVirtual()) {
265 if (
MRI->getRegClass(
T) != DoubleRC)
273 AssocMap[
T].insert(R);
284 if (Visited.count(R))
287 unsigned ThisP = FixedRegs[
x] ? 0 : NextP++;
290 for (
unsigned i = 0; i < WorkQ.size(); ++i) {
291 unsigned T = WorkQ[i];
292 if (Visited.count(
T))
297 USet &Asc = AssocMap[
T];
303 P2Rs[
I.second].insert(
I.first);
308 if (Imm == 0 || Imm == 0xFFFFFFFF)
313int32_t HexagonSplitDoubleRegs::profit(
const MachineInstr *
MI)
const {
315 unsigned Opc =
MI->getOpcode();
317 case TargetOpcode::PHI:
318 for (
const auto &
Op :
MI->operands())
322 case TargetOpcode::COPY:
323 if (
MI->getOperand(1).getSubReg() != 0)
327 case Hexagon::L2_loadrd_io:
328 case Hexagon::S2_storerd_io:
330 case Hexagon::L2_loadrd_pi:
331 case Hexagon::S2_storerd_pi:
334 case Hexagon::A2_tfrpi:
335 case Hexagon::CONST64: {
337 unsigned Lo =
D & 0xFFFFFFFFULL;
338 unsigned Hi =
D >> 32;
341 case Hexagon::A2_combineii:
342 case Hexagon::A4_combineii: {
347 return Prof1 + Prof2;
349 case Hexagon::A4_combineri:
353 case Hexagon::A4_combineir: {
358 if (V == 0 || V == -1)
364 case Hexagon::A2_combinew:
367 case Hexagon::A2_sxtw:
370 case Hexagon::A2_andp:
371 case Hexagon::A2_orp:
372 case Hexagon::A2_xorp: {
375 return profit(Rs) + profit(Rt);
378 case Hexagon::S2_asl_i_p_or: {
379 unsigned S =
MI->getOperand(3).getImm();
380 if (S == 0 || S == 32)
384 case Hexagon::S2_asl_i_p:
385 case Hexagon::S2_asr_i_p:
386 case Hexagon::S2_lsr_i_p:
387 unsigned S =
MI->getOperand(2).getImm();
388 if (S == 0 || S == 32)
400int32_t HexagonSplitDoubleRegs::profit(
Register Reg)
const {
405 case Hexagon::A2_tfrpi:
406 case Hexagon::CONST64:
407 case Hexagon::A2_combineii:
408 case Hexagon::A4_combineii:
409 case Hexagon::A4_combineri:
410 case Hexagon::A4_combineir:
411 case Hexagon::A2_combinew:
419bool HexagonSplitDoubleRegs::isProfitable(
const USet &Part, LoopRegMap &IRM)
421 unsigned FixedNum = 0, LoopPhiNum = 0;
424 for (
unsigned DR : Part) {
426 int32_t
P = profit(DefI);
427 if (
P == std::numeric_limits<int>::min())
431 if (isInduction(DR, IRM))
434 for (
auto U =
MRI->use_nodbg_begin(DR), W =
MRI->use_nodbg_end();
437 if (isFixedInstr(UseI)) {
441 if (
Op.isReg() && Part.count(
Op.getReg()))
454 if (L &&
L->getHeader() ==
PB)
458 int32_t
P = profit(UseI);
459 if (
P == std::numeric_limits<int>::min())
465 if (FixedNum > 0 && LoopPhiNum > 0)
466 TotalP -= 20*LoopPhiNum;
474void HexagonSplitDoubleRegs::collectIndRegsForLoop(
const MachineLoop *L,
490 if (BadLB ||
Cond.size() != 2)
496 if (TB != HB && FB != HB)
498 assert(
Cond[1].
isReg() &&
"Unexpected Cond vector from analyzeBranch");
501 assert(
MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass);
507 while (CmpI->
getOpcode() == Hexagon::C2_not)
510 int64_t
Mask = 0, Val = 0;
515 if (CmpR1 &&
MRI->getRegClass(CmpR1) != DoubleRC)
517 if (CmpR2 &&
MRI->getRegClass(CmpR2) != DoubleRC)
519 if (!CmpR1 && !CmpR2)
529 using UVect = std::vector<unsigned>;
532 for (
auto &
MI : *HB) {
537 if (
MRI->getRegClass(R) == DoubleRC)
543 auto NoIndOp = [
this, CmpR1, CmpR2] (
unsigned R) ->
bool {
544 for (
auto I =
MRI->use_nodbg_begin(R), E =
MRI->use_nodbg_end();
547 if (UseI->
getOpcode() != Hexagon::A2_addp)
553 if (
T == CmpR1 ||
T == CmpR2)
559 Rs.insert(DP.begin(),
End);
565 dump_partition(
dbgs(), Rs, *
TRI);
570void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) {
571 using LoopVector = std::vector<MachineLoop *>;
576 for (
unsigned i = 0; i < WorkQ.size(); ++i)
582 collectIndRegsForLoop(L, Rs);
584 IRM.insert(std::make_pair(L, Rs));
588void HexagonSplitDoubleRegs::createHalfInstr(
unsigned Opc,
MachineInstr *
MI,
589 const UUPairMap &PairMap,
unsigned SubR) {
594 for (
auto &
Op :
MI->operands()) {
601 unsigned SR =
Op.getSubReg();
602 bool isVirtReg =
R.isVirtual();
603 bool isKill =
Op.isKill();
604 if (isVirtReg &&
MRI->getRegClass(R) == DoubleRC) {
606 UUPairMap::const_iterator
F = PairMap.find(R);
607 if (
F == PairMap.end()) {
610 const UUPair &
P =
F->second;
611 R = (SubR == Hexagon::isub_lo) ?
P.first :
P.second;
616 Op.isDead(),
Op.isUndef(),
Op.isEarlyClobber(), SR,
Op.isDebug(),
617 Op.isInternalRead());
623 const UUPairMap &PairMap) {
624 bool Load =
MI->mayLoad();
625 unsigned OrigOpc =
MI->getOpcode();
626 bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi ||
627 OrigOpc == Hexagon::S2_storerd_pi);
639 :
MI->getOperand(2));
640 UUPairMap::const_iterator
F = PairMap.find(ValOp.
getReg());
644 const UUPair &
P =
F->second;
653 const UUPair &
P =
F->second;
667 int64_t Inc =
Load ?
MI->getOperand(3).getImm()
668 :
MI->getOperand(2).getImm();
676 MRI->replaceRegWith(UpdOp.
getReg(), NewR);
682 for (
auto &MO :
MI->memoperands()) {
696 const UUPairMap &PairMap) {
704 UUPairMap::const_iterator
F = PairMap.find(Op0.
getReg());
706 const UUPair &
P =
F->second;
717 .
addImm(int32_t(V & 0xFFFFFFFFULL));
719 .
addImm(int32_t(V >> 32));
723 const UUPairMap &PairMap) {
731 UUPairMap::const_iterator
F = PairMap.find(Op0.
getReg());
733 const UUPair &
P =
F->second;
753 const UUPairMap &PairMap) {
760 UUPairMap::const_iterator
F = PairMap.find(Op0.
getReg());
762 const UUPair &
P =
F->second;
773 const UUPairMap &PairMap) {
774 using namespace Hexagon;
780 int64_t Sh64 = Op2.
getImm();
781 assert(Sh64 >= 0 && Sh64 < 64);
784 UUPairMap::const_iterator
F = PairMap.find(Op0.
getReg());
786 const UUPair &
P =
F->second;
790 unsigned Opc =
MI->getOpcode();
791 bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p);
793 bool Signed = (Opc == S2_asr_i_p);
799 : (
Signed ? S2_asr_i_r : S2_lsr_i_r);
800 unsigned LoSR = isub_lo;
801 unsigned HiSR = isub_hi;
832 else if (S == 16 &&
Signed)
863 }
else if (S == 32) {
878 else if (S == 16 &&
Signed)
897 const UUPairMap &PairMap) {
898 using namespace Hexagon;
905 int64_t Sh64 = Op3.
getImm();
906 assert(Sh64 >= 0 && Sh64 < 64);
909 UUPairMap::const_iterator
F = PairMap.find(Op0.
getReg());
911 const UUPair &
P =
F->second;
912 unsigned LoR =
P.first;
913 unsigned HiR =
P.second;
921 unsigned LoSR = isub_lo;
922 unsigned HiSR = isub_hi;
951 Register TmpR1 =
MRI->createVirtualRegister(IntRC);
956 Register TmpR2 =
MRI->createVirtualRegister(IntRC);
964 }
else if (S == 32) {
990 const UUPairMap &PairMap) {
991 using namespace Hexagon;
995 unsigned Opc =
MI->getOpcode();
998 case TargetOpcode::PHI:
999 case TargetOpcode::COPY: {
1001 if (
MRI->getRegClass(DstR) == DoubleRC) {
1002 createHalfInstr(Opc,
MI, PairMap, isub_lo);
1003 createHalfInstr(Opc,
MI, PairMap, isub_hi);
1009 createHalfInstr(A2_and,
MI, PairMap, isub_lo);
1010 createHalfInstr(A2_and,
MI, PairMap, isub_hi);
1014 createHalfInstr(A2_or,
MI, PairMap, isub_lo);
1015 createHalfInstr(A2_or,
MI, PairMap, isub_hi);
1019 createHalfInstr(A2_xor,
MI, PairMap, isub_lo);
1020 createHalfInstr(A2_xor,
MI, PairMap, isub_hi);
1028 splitMemRef(
MI, PairMap);
1034 splitImmediate(
MI, PairMap);
1043 splitCombine(
MI, PairMap);
1048 splitExt(
MI, PairMap);
1055 splitShift(
MI, PairMap);
1060 splitAslOr(
MI, PairMap);
1073 const UUPairMap &PairMap) {
1074 for (
auto &
Op :
MI->operands()) {
1075 if (!
Op.isReg() || !
Op.isUse() || !
Op.getSubReg())
1078 UUPairMap::const_iterator
F = PairMap.find(R);
1079 if (
F == PairMap.end())
1081 const UUPair &
P =
F->second;
1082 switch (
Op.getSubReg()) {
1083 case Hexagon::isub_lo:
1086 case Hexagon::isub_hi:
1087 Op.setReg(
P.second);
1095 const UUPairMap &PairMap) {
1099 for (
auto &
Op :
MI->operands()) {
1100 if (!
Op.isReg() || !
Op.isUse())
1105 if (
MRI->getRegClass(R) != DoubleRC ||
Op.getSubReg())
1107 UUPairMap::const_iterator
F = PairMap.find(R);
1108 if (
F == PairMap.end())
1110 const UUPair &Pr =
F->second;
1111 Register NewDR =
MRI->createVirtualRegister(DoubleRC);
1114 .
addImm(Hexagon::isub_lo)
1116 .
addImm(Hexagon::isub_hi);
1121bool HexagonSplitDoubleRegs::splitPartition(
const USet &Part) {
1122 using MISet = std::set<MachineInstr *>;
1125 bool Changed =
false;
1128 dump_partition(
dbgs(), Part, *
TRI);
dbgs() <<
'\n');
1133 for (
unsigned DR : Part) {
1135 SplitIns.insert(DefI);
1139 for (
auto U =
MRI->use_nodbg_begin(DR),
W =
MRI->use_nodbg_end();
1141 SplitIns.insert(
U->getParent());
1148 PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR)));
1152 for (
auto *
MI : SplitIns) {
1153 if (isFixedInstr(
MI)) {
1154 collapseRegPairs(
MI, PairMap);
1156 bool Done = splitInstr(
MI, PairMap);
1163 for (
unsigned DR : Part) {
1168 for (
auto U =
MRI->use_nodbg_begin(DR), W =
MRI->use_nodbg_end();
1170 Uses.insert(
U->getParent());
1171 for (
auto *M :
Uses)
1172 replaceSubregUses(M, PairMap);
1175 for (
auto *
MI : Erase) {
1183bool HexagonSplitDoubleRegs::runOnMachineFunction(
MachineFunction &MF) {
1191 TRI =
ST.getRegisterInfo();
1192 TII =
ST.getInstrInfo();
1194 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1199 collectIndRegs(IRM);
1200 partitionRegisters(P2Rs);
1203 dbgs() <<
"Register partitioning: (partition #0 is fixed)\n";
1204 for (UUSetMap::iterator
I = P2Rs.begin(), E = P2Rs.end();
I != E; ++
I) {
1205 dbgs() <<
'#' <<
I->first <<
" -> ";
1206 dump_partition(
dbgs(),
I->second, *
TRI);
1211 bool Changed =
false;
1214 for (UUSetMap::iterator
I = P2Rs.begin(), E = P2Rs.end();
I != E; ++
I) {
1217 if (Limit >= 0 && Counter >= Limit)
1219 USet &Part =
I->second;
1222 if (!isProfitable(Part, IRM))
1225 Changed |= splitPartition(Part);
1232 return new HexagonSplitDoubleRegs();
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Rewrite Partial Register Uses
const HexagonInstrInfo * TII
static cl::opt< bool > MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true), cl::desc("Do not split loads or stores"))
static cl::opt< bool > SplitAll("hsdr-split-all", cl::Hidden, cl::init(false), cl::desc("Split all partitions"))
static cl::opt< int > MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1), cl::desc("Maximum number of split partitions"))
static int32_t profitImm(unsigned Imm)
unsigned const TargetRegisterInfo * TRI
static bool isReg(const MCInst &MI, unsigned OpNo)
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
static const MCPhysReg DoubleRegs[32]
support::ulittle16_t & Lo
support::ulittle16_t & Hi
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &Mask, int64_t &Value) const override
For a comparison instruction, return the source registers in SrcReg and SrcReg2 if having two registe...
bool PredOpcodeHasJMP_c(unsigned Opcode) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
iterator_range< mop_iterator > operands()
const MachineOperand & getOperand(unsigned i) const
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
Flags
Flags values. These may be or'd together.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
static unsigned virtReg2Index(Register Reg)
Convert a virtual register number to a 0-based index.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void initializeHexagonSplitDoubleRegsPass(PassRegistry &)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
unsigned getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
FunctionPass * createHexagonSplitDoubleRegs()
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
This struct is a compact representation of a valid (non-zero power of two) alignment.
This class contains a discriminated union of information about pointers in memory operands,...