Buggy python submission (verdict: Time Limit Exceeded):
class GE():
    def __init__(self, A, mod):
        self.N = len(A)
        self.M = len(A[0])
        self.A = A[:]
        self.mod = mod
        self.uptri = None
        self.pivot = []
        self.R = None
        
    def ut(self):
        if self.uptri is not None:
            return self.uptri
        self.uptri = self.A[:]
        
        c = 0
        for i in range(self.N):
            if i + c >= self.M:
                break
            while self.uptri[i][i+c] == 0:
                for j in range(i+1, self.N):
                    if self.uptri[j][i+c]:
                        self.uptri[i], self.uptri[j] = self.uptri[j], self.uptri[i]
                        break
                else:
                    c += 1
                    if i + c == self.M:
                        return self.uptri
            self.pivot.append((i, i+c))
            t = pow(self.uptri[i][i+c], self.mod - 2, self.mod)
            for j in range(i+1, self.N):
                tj = t * self.uptri[j][i+c]
                self.uptri[j][i+c:] = [(aj - tj*ai) % self.mod for ai, aj in zip(self.uptri[i][i+c:], self.uptri[j][i+c:])]
            for pi, pj in self.pivot[::-1]:
                t = pow(self.uptri[pi][pj], self.mod-2, self.mod)
                self.uptri[pi][pj:] = [(ai * t) % self.mod for ai in self.uptri[pi][pj:]]
                for i in range(pi-1, -1, -1):
                    ti = self.uptri[i][pj]
                    self.uptri[i][pj:] = [(ai - api*ti) % self.mod for ai, api in zip(self.uptri[i][pj:], self.uptri[pi][pj:])]
        
        return self.uptri
    def rank(self):
        if self.R is not None:
            return self.R
        self.ut()
        self.R = len(self.pivot)
        return self.R

N, M = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]
mod = 998244353
T = GE(A, 2)
print((pow(2, N+M-1, mod) - pow(2, N+M-T.rank()-1, mod)) % mod)


Fixed submission:
class GE():
    def __init__(self, A, mod):
        self.N = len(A)
        self.M = len(A[0])
        self.A = A[:]
        self.mod = mod
        self.uptri = None
        self.pivot = []
        self.R = None
    def ut(self):
        if self.uptri is not None:
            return self.uptri
        self.uptri = self.A[:]
        
        c = 0
        for i in range(self.N):
            if i + c >= self.M:
                break
            while self.uptri[i][i+c] == 0:
                for j in range(i+1, self.N):
                    if self.uptri[j][i+c]:
                        self.uptri[i], self.uptri[j] = self.uptri[j], self.uptri[i]
                        break
                else:
                    c += 1
                    if i + c == self.M:
                        return self.uptri
            self.pivot.append((i, i+c))
            t = pow(self.uptri[i][i+c], self.mod - 2, self.mod)
            for j in range(i+1, self.N):
                tj = t * self.uptri[j][i+c]
                self.uptri[j][i+c:] = [(aj - tj*ai) % self.mod for ai, aj in zip(self.uptri[i][i+c:], self.uptri[j][i+c:])]
        for pi, pj in self.pivot[::-1]:
            t = pow(self.uptri[pi][pj], self.mod-2, self.mod)
            self.uptri[pi][pj:] = [(ai * t) % self.mod for ai in self.uptri[pi][pj:]]
            for i in range(pi-1, -1, -1):
                ti = self.uptri[i][pj]
                self.uptri[i][pj:] = [(ai - api*ti) % self.mod for ai, api in zip(self.uptri[i][pj:], self.uptri[pi][pj:])]
        
        return self.uptri
    def rank(self):
        if self.R is not None:
            return self.R
        self.ut()
        self.R = len(self.pivot)
        return self.R
N, M = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]
mod = 998244353
T = GE(A, 2)
print((pow(2, N+M-1, mod) - pow(2, N+M-T.rank()-1, mod)) % mod)