Index: apply.sh =================================================================== --- /dev/null +++ apply.sh @@ -0,0 +1,6 @@ +#!/bin/bash +for name in "$@" +do + python3 `dirname "$0"`/update.py < "$name" > "$name.tmp" && mv "$name.tmp" "$name" + rm -f "$name.tmp" +done Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -293,7 +293,7 @@ FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval] FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval] - FUNC_CODE_INST_GEP = 4, // GEP: [n x operands] + FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands] FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval] FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval] FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval] @@ -327,7 +327,7 @@ FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred] // new select on i1 or [N x i1] FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred] - FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands] FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...] // 32 is unused. FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN @@ -345,8 +345,9 @@ FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...] FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol, // ordering, synchscope] - FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol + FUNC_CODE_INST_STOREATOMIC = 42, // STORE: [ptrty,ptr,val, align, vol // ordering, synchscope] + FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands] }; enum UseListCodes { Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -845,6 +845,13 @@ return cast(Instruction::getType()); } + Type *getSourceElementType() const { + SequentialType *Ty = cast(getPointerOperandType()); + if (VectorType *VTy = dyn_cast(Ty)) + Ty = cast(VTy->getElementType()); + return Ty->getElementType(); + } + /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { // Note that this is always the same as the pointer operand's address space Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -3062,9 +3062,22 @@ InstructionList.push_back(I); break; } - case bitc::FUNC_CODE_INST_INBOUNDS_GEP: - case bitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands] + case bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD: + case bitc::FUNC_CODE_INST_GEP_OLD: + case bitc::FUNC_CODE_INST_GEP: { // GEP: type, [n x operands] unsigned OpNum = 0; + + Type *Ty; + bool InBounds; + + if (BitCode == bitc::FUNC_CODE_INST_GEP) { + InBounds = Record[OpNum++]; + Ty = getTypeByID(Record[OpNum++]); + } else { + InBounds = BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD; + Ty = nullptr; + } + Value *BasePtr; if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr)) return Error("Invalid record"); @@ -3078,8 +3091,9 @@ } I = GetElementPtrInst::Create(BasePtr, GEPIdx); + assert(!Ty || Ty == cast(I)->getSourceElementType()); InstructionList.push_back(I); - if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP) + if (InBounds) cast(I)->setIsInBounds(true); break; } Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -56,7 +56,8 @@ FUNCTION_INST_CAST_ABBREV, FUNCTION_INST_RET_VOID_ABBREV, FUNCTION_INST_RET_VAL_ABBREV, - FUNCTION_INST_UNREACHABLE_ABBREV + FUNCTION_INST_UNREACHABLE_ABBREV, + FUNCTION_INST_GEP_ABBREV, }; static unsigned GetEncodedCastOpcode(unsigned Opcode) { @@ -1675,13 +1676,16 @@ } break; - case Instruction::GetElementPtr: + case Instruction::GetElementPtr: { Code = bitc::FUNC_CODE_INST_GEP; - if (cast(&I)->isInBounds()) - Code = bitc::FUNC_CODE_INST_INBOUNDS_GEP; + AbbrevToUse = FUNCTION_INST_GEP_ABBREV; + auto &GEPInst = cast(I); + Vals.push_back(GEPInst.isInBounds()); + Vals.push_back(VE.getTypeID(GEPInst.getSourceElementType())); for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) PushValueAndType(I.getOperand(i), InstID, Vals, VE); break; + } case Instruction::ExtractValue: { Code = bitc::FUNC_CODE_INST_EXTRACTVAL; PushValueAndType(I.getOperand(0), InstID, Vals, VE); @@ -2284,6 +2288,18 @@ Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } + { + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_GEP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty + Log2_32_Ceil(VE.getTypes().size() + 1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_GEP_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } Stream.ExitBlock(); } Index: test/Bitcode/function-encoding-rel-operands.ll =================================================================== --- test/Bitcode/function-encoding-rel-operands.ll +++ test/Bitcode/function-encoding-rel-operands.ll @@ -35,9 +35,9 @@ ; CHECK: FUNCTION_BLOCK -; skip checking operands of INST_INBOUNDS_GEP since that depends on ordering +; skip checking operands of INST_GEP since that depends on ordering ; between literals and the formal parameters. -; CHECK: INST_INBOUNDS_GEP {{.*}} +; CHECK: INST_GEP {{.*}} ; CHECK: INST_LOAD {{.*}}op0=1 {{.*}} ; CHECK: INST_CMP2 op0=1 {{.*}} ; CHECK: INST_RET {{.*}}op0=1 Index: tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp =================================================================== --- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -222,8 +222,10 @@ case bitc::FUNC_CODE_INST_BINOP: return "INST_BINOP"; case bitc::FUNC_CODE_INST_CAST: return "INST_CAST"; - case bitc::FUNC_CODE_INST_GEP: return "INST_GEP"; - case bitc::FUNC_CODE_INST_INBOUNDS_GEP: return "INST_INBOUNDS_GEP"; + case bitc::FUNC_CODE_INST_GEP_OLD: + return "INST_GEP_OLD"; + case bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD: + return "INST_INBOUNDS_GEP_OLD"; case bitc::FUNC_CODE_INST_SELECT: return "INST_SELECT"; case bitc::FUNC_CODE_INST_EXTRACTELT: return "INST_EXTRACTELT"; case bitc::FUNC_CODE_INST_INSERTELT: return "INST_INSERTELT"; @@ -248,6 +250,8 @@ case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: return "DEBUG_LOC_AGAIN"; case bitc::FUNC_CODE_INST_CALL: return "INST_CALL"; case bitc::FUNC_CODE_DEBUG_LOC: return "DEBUG_LOC"; + case bitc::FUNC_CODE_INST_GEP: + return "INST_GEP"; } case bitc::VALUE_SYMTAB_BLOCK_ID: switch (CodeID) { Index: update-gep-explicit-type.py =================================================================== --- /dev/null +++ update-gep-explicit-type.py @@ -0,0 +1,29 @@ +import fileinput +import sys +import re + +ib = re.compile("getelementptr inbounds +[^( ]") +norm = re.compile("getelementptr +[^( ]") + +ibrep = re.compile(r"(^.*?getelementptr inbounds )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))") +normrep = re.compile( r"(^.*?getelementptr )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))") + +def conv(match, line): + if not match: + return line + line = match.groups()[0] + if len(match.groups()[5]) == 0: + line += match.groups()[2] + line += match.groups()[3] + line += ", " + line += match.groups()[1] + line += "\n" + return line + +for line in sys.stdin: + if line.find("getelementptr ") == line.find("getelementptr inbounds"): + if line.find("getelementptr inbounds") != line.find("getelementptr inbounds ("): + line = conv(re.match(ibrep, line), line) + elif line.find("getelementptr ") != line.find("getelementptr ("): + line = conv(re.match(normrep, line), line) + sys.stdout.write(line) Index: update.py =================================================================== --- /dev/null +++ update.py @@ -0,0 +1,8 @@ +import fileinput +import sys +import re + +pat = re.compile(r"((?:=|:|^)\s*load (?:atomic )?(?:volatile )?(.*?))(| addrspace\(\d+\) *)\*($| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$)") + +for line in sys.stdin: + sys.stdout.write(re.sub(pat, r"\1, \2\3*\4", line))