2013-06-10 10 views
7

Próbuję zoptymalizować ocenę wyrażeń w kompilatorze.Jak uprościć arytmetyczne wyrażenie w stylu C zawierające zmienne podczas generowania kodu?

Wyrażenia arytmetyczne mają styl litery C i mogą zawierać zmienne. Mam nadzieję uprościć wyrażenia tak bardzo, jak to możliwe.

Na przykład (3+100*A*B+100)*3+100 można uprościć do 409+300*A*B.

Jest to głównie zależne od prawa rozdzielczego, prawa asocjacyjnego i prawa przemiennego.

Główną trudnością, jaką napotykam, jest łączenie tych praw arytmetycznych z tradycyjnymi algorytmami oceny stosu.

Czy ktoś może podzielić się doświadczeniami związanymi z tym lub podobnymi problemami w kontekście budowania kompilatora?

+0

Tylko '+ - * /' i nawiasy? –

+0

@CaseyChu W rzeczywistości mogą pojawić się wszyscy operatorzy C. Ale myślę, że tylko uwzględnienie + - * /() jest również dopuszczalne. Staram się jak najlepiej "uprościć je. – konjac

+2

Prawdopodobnie musisz opracować [system przepisywania] (http://en.wikipedia.org/wiki/Rewriting), który będzie sukcesywnie stosować reguły przepisywania do wyrażenia. Zanim to zrobisz, możesz rzucić okiem na istniejący kod źródłowy kompilatora, aby zobaczyć, jak radzi sobie z takimi optymalizacjami. Słyszałem, że kod źródłowy LLVM jest bardzo czytelny. –

Odpowiedz

1

Zastosuj constant folding w połączeniu z redukcją siły podczas przebiegu generowania kodu kompilacji. Większość tekstów kompilatora zapewni algorytm do implementacji tego.

1

Kompilatory zazwyczaj mają pewne wewnętrzne reguły normalizacji, takie jak "stałe po lewej stronie". Oznacza to, że a + 3 zostanie przekształcony w , ale nie na odwrót.

W przykładzie (3+100*A*B+100)*3+100 by znormalizować do (3+100+(100*A*B))*3+100. Teraz jest jasne, aby zoptymalizować 3+100.

Inna transformacja może być a*C1+C2 w (a+(C2/C1))*C1 pod warunkiem, że C1 isą stałe. Intuicyjnie normalizuje to "dodawanie przed pomnożeniem".

Te normalizacje nie są optymalizacjami. Zamierzeniem jest głównie łączenie stałych grup, więc stałe fałdowanie jest bardziej skuteczne.