技術文章:scf編譯器對C語言的邏輯運算符的優化

2022年10月16日20:12:32 科技 1285

在各種編程語言里,邏輯運算符都是要短路的。

C語言為例:

if (p && p->x > 0) p->x++;

當指針p是NULL的時候,對成員變量p->x的讀寫會導致段錯誤,所以如果&&之前的條件p是NULL就要把後面的p->x跳過去。

這樣才能保證代碼的正常運行。

如果語言本身不支持邏輯運算符的短路,那麼代碼就只能這麼寫了:

if (p) {

if (p->x > 0) p->x++;

}

要多寫一個if條件。

邏輯運算符的結果只有0或1兩種。

在編程里,邏輯運算符既可以作為if / while / for的條件表達式還可以參與普通運算

if (i > 0 && j > 1 && k > 2) return -1; // 條件表達式

n = i > 0 && j > 1 && k > 2; // 普通運算

在對邏輯運算符進行優化時,必須同時考慮這兩種情況

第2種情況下,如果邏輯運算符在計算前2個條件時短路了,必須把計算結果寫入最後一個邏輯運算符對應的臨時變量

最後一個邏輯運算符的計算結果,才是整個表達式的結果,也是對n賦值的結果。

如果只是在if語句里作為條件表達式,邏輯運算的結果不需要寫到臨時變量里,直接根據比較結果跳轉到對應的分支就可以了。

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

賦值運算的語法樹

第2種情況的語法樹如圖,參與賦值運算的是第2個&&對應的臨時變量。

如果在i > 0 或 j > 1時短路的話,它們設置的是第1個&&的值:編譯器在短路跳轉時必須給第2個&&設置運算結果,否則之後的n = ...的結果就不對了。

邏輯運算符生成中間代碼的時候,實際上並不知道它的結果以後會被怎麼使用[捂臉]

從上圖中也可以看出=號在更上面(if也是在更上面),實際上,在處理&&運算符時只能看到它的2個條件表達式,看不到更上層的程序邏輯。

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

if條件的語法樹

如果硬要去看更高層的邏輯,就會破壞模塊封裝性,讓遍歷語法樹生成中間代碼的代碼變得複雜、難看。

scf框架在這裡的處理是:

1,先給所有邏輯運算符的臨時變量設置上結果,把進一步的優化放到以後

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

if的情況

最初的中間代碼是這樣的,可以看到每個cmpteq運算之後都緊跟着setcc

其中cmp是比較大小,結果可以是>、==、<、>=、<=、!=。

teq是比較是不是0,結果只有2種:== 0,!= 0。

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

賦值的情況

在有邏輯運算符的情況下,在cmp之後必然跟着teq去判斷邏輯結果是不是0。

例如上圖中的:

cmp i, 0

setgt v_8_16/&&

jle : teq v_8_16/&&

跳轉的目標代碼是:

teq v_8_16/&&

setnz v_8_25/&&

jz : assign v_8_6/n; v_8_25/&&

數字表示的是行列號,v_8_16/&&表示第8行第16列的&&運算符對應的臨時變量

可以看出,在最初的中間代碼里,邏輯運算符並沒有“真正的短路”:雖然跳過了第2個比較條件,但並沒有跳過邏輯運算。

之所以這樣,就是因為(生成中間代碼時)沒法確定邏輯結果接下來還有沒有用。

既然沒法確定,編譯器就只能先當它有用:代碼里遇到這種情況,是一定會做保守處理的。

所以說,不管是程序員還是數學家,一般都是悲觀主義者[捂臉]

2,跳轉優化時,對這個問題進一步的優化。

如果一個跳轉的目標位置是一個絕對跳轉,就可以把它優化成跳轉到這個絕對跳轉的目標位置。

if a jcc's destination is a jmp, then optimize its destination to the jmp's.

這是對跳轉的基本優化。

實際上,如果跳轉之前對邏輯結果設置了false,而跳轉的目標又是檢測這個結果的話,那麼檢測結果也是false[呲牙]這是跳轉優化的另一條規則。

所以說,在cmp觸發了jle (<=) 的情況下,那麼它倆之間的setgt (>) 就肯定是0

進而導致目標位置的teq也是0

進而導致目標位置的setnz也是0

進而導致目標位置的jz被觸發,

所以,jle的地址就是jz的地址

但在jle之前要把setnz的目標變量也設置一下,使用的設置指令是setgt:與最初觸發跳轉的條件一致。

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

跳轉優化之後的中間代碼

從上圖可以看出,經過跳轉優化之後,測試邏輯結果的teq運算消失了,與teq對應的jz跳轉也消失了:

邏輯運算符被短路到了接下來的賦值運算。

賦值運算只使用最後一個臨時變量v_8_25。

對中間臨時變量v_8_16的設置是多餘的,接下來的問題是怎麼消除它。

如果邏輯運算只是作為if的條件的話,那麼最後一個邏輯結果也是不需要的

3,基於活躍變量分析的優化,

算術運算會使用最後一個邏輯結果的臨時變量,if條件不使用任何邏輯結果的臨時變量,這在臨時變量的活躍度上可以體現出來。

不活躍的臨時變量DAG上去掉就行了。

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

最終的優化結果

對n的賦值運算只使用臨時變量v_8_25,可以看出它是前面基本塊的出口活躍變量,被保留了下來。

如果是if條件,因為所有的臨時變量都不活躍,在DAG優化之後就只剩下比較和跳轉了[呲牙]

如下圖:

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

if最終的圖

上圖是if條件的最終的圖,下圖是跳轉優化之後、DAG優化之前的圖。

可以看到,所有的setgt都被去掉了。

技術文章:scf編譯器對C語言的邏輯運算符的優化 - 天天要聞

if之前的圖

科技分類資訊推薦

所謂“大而美”法案或將繼續擴大美債規模 - 天天要聞

所謂“大而美”法案或將繼續擴大美債規模

美國所謂“大而美”法案7月1日在國會參議院得到通過,當前還需要得到眾議院的通過才能提交給美國總統簽字。如果該法案最終通過並成為法律,預計將對已創下紀錄的美國聯邦政府債務增加壓力。美國國會預算辦公室估....
解碼哈葯618 突圍路徑:從產品矩陣到生態構建的行業示範 - 天天要聞

解碼哈葯618 突圍路徑:從產品矩陣到生態構建的行業示範

當 2025 年 "618" 電商大促成為檢驗消費市場韌性的試金石,哈葯以國民葯企的戰略定力與創新突破,構建起一套 "傳統賽道築基 + 新興領域破局" 的增長模型。在保健品行業競爭白熱化的背景下,這家企業通過多品牌協同、產品創新迭代與數字化營銷破圈,不僅鞏固了細分市場領導地位,更以全鏈路生態布局為大健康產業提供了可複製...
更快,更強,更純粹!超薄極致電競利器ROG絕神OLED顯示器 - 天天要聞

更快,更強,更純粹!超薄極致電競利器ROG絕神OLED顯示器

熟悉鼠鼠我的朋友都知道我是一個遊戲愛好者,無論是喊上朋友們一起開黑還是自己沉浸式體驗製作精良的3A大作,都能在平時繁重的牛馬生活之餘帶給我放鬆和快樂。作為重度遊戲愛好者,外設的選擇自然是馬虎不得,這其中我最為看重的就是能夠直接影響平時遊戲體
坐飛機和高鐵分別可以攜帶什麼樣的充電寶? - 天天要聞

坐飛機和高鐵分別可以攜帶什麼樣的充電寶?

來源:【江西發布】近日民航局禁止攜帶沒有3C標識、被召回範圍的充電寶上機規定引發關注坐飛機和高鐵分別可以攜帶什麼樣的充電寶?充電寶上飛機乘坐飛機時,充電寶只能在手提行李中攜帶或隨身攜帶,嚴禁在託運行李中攜帶。
小米YU7“封神” 國產新能源汽車“新王換舊王” - 天天要聞

小米YU7“封神” 國產新能源汽車“新王換舊王”

摘要:新能源的新格局,雛形已現。鳳凰網科技 出品2025年6月26日夜晚,小米旗下首款SUV車型小米YU 7正式發布。這款以豪華、高性能、極致體驗、先進安全性為特徵的SUV車型,猶如一顆重磅核彈投入本就不平靜的新能源車市,激起千層浪。
百度前副總裁璩靜開醫美診所,人均消費2218元 - 天天要聞

百度前副總裁璩靜開醫美診所,人均消費2218元

紅星資本局7月2日消息,百度前副總裁璩靜在華為總部坂田基地附近開了一家醫美診所。據公開資料,璩靜名下新增一家存續企業——深圳大為診所。該診所成立於2024年12月23日,璩靜持股比例為100%,認繳出資額為100萬元,經營範圍為診所服務等。
千里智行,常用常新,傳祺嚮往S7 開啟重磅OTA升級 - 天天要聞

千里智行,常用常新,傳祺嚮往S7 開啟重磅OTA升級

7月2日,傳祺嚮往S7 OTA如期而至,OTA 2.0版本正式全量推送。本次升級新增16項功能,31項 功能升級和57項體驗優化,主要涉及智能座艙、智能輔助駕駛、娛樂系統、車機交互等多個維度,旨在為用戶提供常用常新的出行體驗,功能強大又好用。
九州風神推出大霜塔稜鏡風冷散熱器:雙塔稜鏡頂蓋,209 元 - 天天要聞

九州風神推出大霜塔稜鏡風冷散熱器:雙塔稜鏡頂蓋,209 元

IT之家 7 月 3 日消息,九州風神 DeepCool 現已推出大霜塔稜鏡 (AG620 ARGB V2) 風冷散熱器。其採用雙塔雙風扇六熱管直觸設計,雙塔頂部均配有 ARGB 燈效“稜鏡頂蓋”。大霜塔稜鏡長寬高 129×136×162 (mm),支持 45mm 高內存條。其六根 6mm 雙向恆定熱平衡熱管採用 CTT 2.0 核心觸控技術在塔體底部並管排