mirror of
https://github.com/intel/intel-graphics-compiler.git
synced 2025-10-30 08:18:26 +08:00
Fix constant folding in PredefinedConstantResolving
PredefinedConstantResolving pass caused type mismatch assertion
in tests while moving to opaque pointers. It happened when there was a
type difference between a global variable and it's load instruction
user. With typed pointers the pass was skipped in this scenario because
user of same global was bitcast and then it's user was load. What this
pass tried to do was doing RAUW operation on load to replace it with
global constant. This fix changes pass's behaviour by enabling constant
folding even when there is a type difference between load instruction
and global constant.
Example crashing ir:
```llvm
@global = constant [3 x i64] [i64 16, i64 32, i64 64]
define void @func(i64 %0) {
%2 = load i64, ptr @global ; <-- crash
ret void
}
```
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
/*========================== begin_copyright_notice ============================
|
||||
|
||||
Copyright (C) 2017-2021 Intel Corporation
|
||||
Copyright (C) 2017-2025 Intel Corporation
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
@ -14,6 +14,7 @@ SPDX-License-Identifier: MIT
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/Pass.h>
|
||||
#include <llvm/Analysis/ConstantFolding.h>
|
||||
#include "common/LLVMWarningsPop.hpp"
|
||||
|
||||
using namespace llvm;
|
||||
@ -39,7 +40,7 @@ ModulePass *IGC::createResolvePredefinedConstantPass() { return new PredefinedCo
|
||||
char PredefinedConstantResolving::ID = 0;
|
||||
|
||||
#define PASS_FLAG "igc-predefined-constant-resolve"
|
||||
#define PASS_DESC "Resolve compiler predefeind constants"
|
||||
#define PASS_DESC "Resolve compiler predefined constants"
|
||||
#define PASS_CFG_ONLY false
|
||||
#define PASS_ANALYSIS false
|
||||
namespace IGC {
|
||||
@ -49,23 +50,24 @@ IGC_INITIALIZE_PASS_END(PredefinedConstantResolving, PASS_FLAG, PASS_DESC, PASS_
|
||||
|
||||
bool PredefinedConstantResolving::runOnModule(Module &M) {
|
||||
bool Changed = false;
|
||||
const DataLayout &DL = M.getDataLayout();
|
||||
|
||||
for (auto &GV : M.globals()) {
|
||||
if (!GV.isConstant())
|
||||
if (!GV.isConstant() || !GV.hasUniqueInitializer())
|
||||
continue;
|
||||
if (!GV.hasUniqueInitializer())
|
||||
continue;
|
||||
// We don't use fancy data structure to reduce the lookup overhead due to
|
||||
// the current limited size of compiler pre-defined constants.
|
||||
|
||||
Constant *C = GV.getInitializer();
|
||||
for (auto I = GV.user_begin(); I != GV.user_end(); /* empty */) {
|
||||
// Ensure we understand how the predefined constant is used.
|
||||
LoadInst *LI = dyn_cast<LoadInst>(*I++);
|
||||
if (!LI)
|
||||
continue;
|
||||
LI->replaceAllUsesWith(C);
|
||||
LI->eraseFromParent();
|
||||
Changed = true;
|
||||
|
||||
if (Constant *Folded = ConstantFoldLoadFromConst(C, LI->getType(), DL)) {
|
||||
LI->replaceAllUsesWith(Folded);
|
||||
LI->eraseFromParent();
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
;=========================== begin_copyright_notice ============================
|
||||
;
|
||||
; Copyright (C) 2025 Intel Corporation
|
||||
;
|
||||
; SPDX-License-Identifier: MIT
|
||||
;
|
||||
;============================ end_copyright_notice =============================
|
||||
|
||||
; REQUIRES: regkeys, llvm-16-plus
|
||||
;
|
||||
; RUN: igc_opt --regkey "EnableOpaquePointersBackend=1" --igc-predefined-constant-resolve 2>&1 -S < %s | FileCheck %s
|
||||
; ------------------------------------------------
|
||||
; PredefinedConstantResolving
|
||||
; ------------------------------------------------
|
||||
|
||||
; This test checks whether the PredefinedConstantResolving pass correctly folds constants with matching or not matching types
|
||||
|
||||
@global_int = internal addrspace(1) constant i32 1337, align 4
|
||||
@global_i8s_arr = internal addrspace(1) constant [8 x i8] [i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8], align 8
|
||||
@global_i64s_arr = internal addrspace(1) constant [3 x i64] [i64 16, i64 32, i64 64], align 8
|
||||
|
||||
; CHECK-LABEL: @test_i64_from_i64_array(
|
||||
; CHECK: store i64 16,
|
||||
; CHECK-NOT: load
|
||||
define spir_kernel void @test_i64_from_i64_array(ptr addrspace(1) %out) {
|
||||
entry:
|
||||
%local = load i64, ptr addrspace(1) @global_i64s_arr, align 8
|
||||
store i64 %local, ptr addrspace(1) %out, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test_direct_i32(
|
||||
; CHECK: store i32 1337,
|
||||
; CHECK-NOT: load
|
||||
define spir_kernel void @test_direct_i32(ptr addrspace(1) %out) {
|
||||
entry:
|
||||
%local = load i32, ptr addrspace(1) @global_int
|
||||
store i32 %local, ptr addrspace(1) %out, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test_i64_from_i8_array(
|
||||
; CHECK: store i64 578437695752307201,
|
||||
; CHECK-NOT: load
|
||||
define spir_kernel void @test_i64_from_i8_array(ptr addrspace(1) %out) {
|
||||
entry:
|
||||
%local = load i64, ptr addrspace(1) @global_i8s_arr, align 8
|
||||
store i64 %local, ptr addrspace(1) %out, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test_i8_from_i64_array(
|
||||
; CHECK: store i8 16,
|
||||
; CHECK-NOT: load
|
||||
define spir_kernel void @test_i8_from_i64_array(ptr addrspace(1) %out) {
|
||||
entry:
|
||||
%local = load i8, ptr addrspace(1) @global_i64s_arr, align 1
|
||||
store i8 %local, ptr addrspace(1) %out, align 1
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { convergent noinline nounwind optnone "less-precise-fpmad"="true" "visaStackCall" }
|
||||
Reference in New Issue
Block a user