@@ -41,7 +41,8 @@ class SinkPointerConstAddPass : public llvm::FunctionPass {
4141 static char ID;
4242
4343private:
44- bool getConstantOffset (llvm::Value *value, int &offset);
44+ bool getConstantOffset (llvm::Value *value, std::vector<llvm::Instruction *> &zexts, int &offset);
45+ void zextToSext (std::vector<llvm::Instruction *> &zexts);
4546};
4647
4748#define PASS_FLAG " igc-sink-ptr-const-add"
@@ -50,7 +51,8 @@ class SinkPointerConstAddPass : public llvm::FunctionPass {
5051#define PASS_ANALYSIS false
5152IGC_INITIALIZE_PASS (SinkPointerConstAddPass, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
5253
53- bool SinkPointerConstAddPass::getConstantOffset(llvm::Value *value, int &offset) {
54+ bool SinkPointerConstAddPass::getConstantOffset(llvm::Value *value, std::vector<llvm::Instruction *> &zexts,
55+ int &offset) {
5456 // Recursively search for constant add operations - this will stop after the first const add found,
5557 // and should be called repeatedly until no more const adds can be sunk.
5658
@@ -61,11 +63,15 @@ bool SinkPointerConstAddPass::getConstantOffset(llvm::Value *value, int &offset)
6163 if (llvm::Instruction *instr = llvm::dyn_cast<llvm::Instruction>(value)) {
6264 if (instr->getOpcode () == llvm::Instruction::Trunc || instr->getOpcode () == llvm::Instruction::ZExt ||
6365 instr->getOpcode () == llvm::Instruction::SExt) {
66+ // Collect zext instructions for later processing
67+ if (instr->getOpcode () == llvm::Instruction::ZExt) {
68+ zexts.push_back (instr);
69+ }
6470 // Skip cast instructions
6571 llvm::Instruction *op = llvm::dyn_cast<llvm::Instruction>(instr->getOperand (0 ));
6672 // This is a simple pass, only sink within the same basic block
6773 if (op && instr->getParent () == op->getParent ()) {
68- return getConstantOffset (instr->getOperand (0 ), offset);
74+ return getConstantOffset (instr->getOperand (0 ), zexts, offset);
6975 } else {
7076 return false ;
7177 }
@@ -89,8 +95,8 @@ bool SinkPointerConstAddPass::getConstantOffset(llvm::Value *value, int &offset)
8995 llvm::Instruction *op0 = llvm::dyn_cast<llvm::Instruction>(instr->getOperand (0 ));
9096 llvm::Instruction *op1 = llvm::dyn_cast<llvm::Instruction>(instr->getOperand (1 ));
9197 // This is a simple pass, only sink within the same basic block
92- return (op0 && instr->getParent () == op0->getParent () && getConstantOffset (op0, offset)) ? true
93- : (op1 && instr->getParent () == op1->getParent ()) ? getConstantOffset (op1, offset)
98+ return (op0 && instr->getParent () == op0->getParent () && getConstantOffset (op0, zexts, offset)) ? true
99+ : (op1 && instr->getParent () == op1->getParent ()) ? getConstantOffset (op1, zexts, offset)
94100 : false ;
95101 }
96102 }
@@ -99,6 +105,19 @@ bool SinkPointerConstAddPass::getConstantOffset(llvm::Value *value, int &offset)
99105 return false ;
100106}
101107
108+ void SinkPointerConstAddPass::zextToSext (std::vector<llvm::Instruction *> &zexts) {
109+ // Remove duplicates
110+ std::sort (zexts.begin (), zexts.end ());
111+ zexts.erase (std::unique (zexts.begin (), zexts.end ()), zexts.end ());
112+ // Convert zext instructions to sext instructions
113+ for (auto &zext : zexts) {
114+ llvm::IRBuilder<> builder (zext);
115+ llvm::Value *sext = builder.CreateSExt (zext->getOperand (0 ), zext->getType ());
116+ zext->replaceAllUsesWith (sext);
117+ zext->eraseFromParent ();
118+ }
119+ }
120+
102121bool SinkPointerConstAddPass::runOnFunction (llvm::Function &F) {
103122 bool changed = false ;
104123 std::vector<llvm::IntToPtrInst *> intToPtrInsts;
@@ -115,11 +134,20 @@ bool SinkPointerConstAddPass::runOnFunction(llvm::Function &F) {
115134
116135 for (auto &intrinsic : intToPtrInsts) {
117136 int offset = 0 ;
137+ bool localChanged = false ;
138+ std::vector<llvm::Instruction *> zexts;
118139 // Keep sinking constant adds until no more can be sunk
119- while (getConstantOffset (intrinsic->getOperand (0 ), offset)) {
140+ while (getConstantOffset (intrinsic->getOperand (0 ), zexts, offset)) {
141+ localChanged = true ;
120142 changed = true ;
121143 }
122144
145+ if (localChanged) {
146+ // In some cases, sinking constant add may introduce negative values in pointer calculations.
147+ // Convert affected zext instructions to sext instructions to avoid potential issues.
148+ zextToSext (zexts);
149+ }
150+
123151 // If we found any constant offset, create new pointer calculation
124152 if (offset != 0 ) {
125153 llvm::IRBuilder<> builder (intrinsic);
0 commit comments